{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ef0a4ee4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C:\\\\Users\\\\IDEA'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%pwd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "japanese-margin",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C:\\\\Users\\\\IDEA'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "os.getcwd()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "executive-insulin",
   "metadata": {},
   "outputs": [],
   "source": [
    "os.chdir('E:\\\\2023\\\\carnivores2023\\\\Carnivoresx30')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "0888b480",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'E:\\\\2023\\\\carnivores2023\\\\Carnivoresx30'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%pwd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d29220ca",
   "metadata": {},
   "outputs": [],
   "source": [
    "from tensorflow import keras\n",
    "keras.__version__\n",
    "import os, shutil"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "d979c4e9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "E:\\2023\\carnivores2023\\Carnivoresx30\n",
      "E:\\2023\\carnivores2023\\Carnivoresx30\\conv\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "original_dir = os.path.abspath('E:\\\\2023\\\\carnivores2023\\\\Carnivoresx30')\n",
    "# The directory where we will\n",
    "# store our smaller dataset\n",
    "base_dir = os.path.join(original_dir, \"conv\")\n",
    "print(original_dir)\n",
    "print(base_dir)\n",
    "# added by reviewer\n",
    "isdir = os.path.isdir(base_dir) \n",
    "print(isdir) \n",
    "\n",
    "if isdir ==True:\n",
    "    shutil.rmtree(base_dir)\n",
    "\n",
    "os.mkdir(base_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6b486b83",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Directories for our training,\n",
    "# validation and test splits\n",
    "train_dir = os.path.join(base_dir, 'train')\n",
    "os.mkdir(train_dir)\n",
    "validation_dir = os.path.join(base_dir, 'validation')\n",
    "os.mkdir(validation_dir)\n",
    "\n",
    "\n",
    "# Directory with our training lion pictures\n",
    "train_lion_dir = os.path.join(train_dir, 'LZP')\n",
    "os.mkdir(train_lion_dir)\n",
    "\n",
    "# Directory with our training leopard pictures\n",
    "train_leop_dir = os.path.join(train_dir, 'LPZP')\n",
    "os.mkdir(train_leop_dir)\n",
    "\n",
    "# Directory with our training hyena pictures\n",
    "train_hyena_dir = os.path.join(train_dir, 'HESP')\n",
    "os.mkdir(train_hyena_dir)\n",
    "\n",
    "# Directory with our training crocodrile pictures\n",
    "train_croc_dir = os.path.join(train_dir, 'CFP')\n",
    "os.mkdir(train_croc_dir)\n",
    "\n",
    "\n",
    "\n",
    "# Directory with our validation lion pictures\n",
    "validation_lion_dir = os.path.join(validation_dir, 'LZP')\n",
    "os.mkdir(validation_lion_dir)\n",
    "\n",
    "# Directory with our validation leopard pictures\n",
    "validation_leop_dir = os.path.join(validation_dir, 'LPZP')\n",
    "os.mkdir(validation_leop_dir)\n",
    "\n",
    "# Directory with our validation hyena pictures\n",
    "validation_hyena_dir = os.path.join(validation_dir, 'HESP')\n",
    "os.mkdir(validation_hyena_dir)\n",
    "\n",
    "# Directory with our validation crocodrile pictures\n",
    "validation_croc_dir = os.path.join(validation_dir, 'CFP')\n",
    "os.mkdir(validation_croc_dir)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "convenient-least",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "197\n",
      "['LZP.208.bmp', 'LZP.87.bmp', 'LZP.10.bmp', 'LZP.15.bmp', 'LZP.194.bmp', 'LZP.52.bmp', 'LZP.76.bmp', 'LZP.130.bmp', 'LZP.234.bmp', 'LZP.151.bmp', 'LZP.183.bmp', 'LZP.204.bmp', 'LZP.78.bmp', 'LZP.176.bmp', 'LZP.253.bmp', 'LZP.212.bmp', 'LZP.121.bmp', 'LZP.138.bmp', 'LZP.233.bmp', 'LZP.201.bmp', 'LZP.191.bmp', 'LZP.221.bmp', 'LZP.147.bmp', 'LZP.32.bmp', 'LZP.232.bmp', 'LZP.152.bmp', 'LZP.2.bmp', 'LZP.47.bmp', 'LZP.246.bmp', 'LZP.224.bmp', 'LZP.46.bmp', 'LZP.173.bmp', 'LZP.26.bmp', 'LZP.235.bmp', 'LZP.39.bmp', 'LZP.108.bmp', 'LZP.259.bmp', 'LZP.59.bmp', 'LZP.216.bmp', 'LZP.203.bmp', 'LZP.238.bmp', 'LZP.174.bmp', 'LZP.131.bmp', 'LZP.257.bmp', 'LZP.29.bmp', 'LZP.82.bmp', 'LZP.91.bmp', 'LZP.104.bmp', 'LZP.65.bmp', 'LZP.27.bmp', 'LZP.164.bmp', 'LZP.184.bmp', 'LZP.85.bmp', 'LZP.202.bmp', 'LZP.22.bmp', 'LZP.218.bmp', 'LZP.50.bmp', 'LZP.182.bmp', 'LZP.227.bmp', 'LZP.23.bmp', 'LZP.189.bmp', 'LZP.143.bmp', 'LZP.86.bmp', 'LZP.141.bmp', 'LZP.163.bmp', 'LZP.100.bmp', 'LZP.5.bmp', 'LZP.102.bmp', 'LZP.135.bmp', 'LZP.31.bmp', 'LZP.94.bmp', 'LZP.37.bmp', 'LZP.14.bmp', 'LZP.3.bmp', 'LZP.134.bmp', 'LZP.73.bmp', 'LZP.75.bmp', 'LZP.25.bmp', 'LZP.109.bmp', 'LZP.79.bmp', 'LZP.252.bmp', 'LZP.159.bmp', 'LZP.101.bmp', 'LZP.144.bmp', 'LZP.66.bmp', 'LZP.150.bmp', 'LZP.129.bmp', 'LZP.54.bmp', 'LZP.177.bmp', 'LZP.217.bmp', 'LZP.33.bmp', 'LZP.43.bmp', 'LZP.148.bmp', 'LZP.64.bmp', 'LZP.55.bmp', 'LZP.179.bmp', 'LZP.124.bmp', 'LZP.117.bmp', 'LZP.58.bmp', 'LZP.156.bmp', 'LZP.13.bmp', 'LZP.260.bmp', 'LZP.178.bmp', 'LZP.199.bmp', 'LZP.6.bmp', 'LZP.188.bmp', 'LZP.119.bmp', 'LZP.231.bmp', 'LZP.0.bmp', 'LZP.4.bmp', 'LZP.206.bmp', 'LZP.132.bmp', 'LZP.12.bmp', 'LZP.56.bmp', 'LZP.71.bmp', 'LZP.21.bmp', 'LZP.225.bmp', 'LZP.255.bmp', 'LZP.210.bmp', 'LZP.162.bmp', 'LZP.237.bmp', 'LZP.74.bmp', 'LZP.161.bmp', 'LZP.53.bmp', 'LZP.17.bmp', 'LZP.51.bmp', 'LZP.146.bmp', 'LZP.118.bmp', 'LZP.249.bmp', 'LZP.185.bmp', 'LZP.198.bmp', 'LZP.187.bmp', 'LZP.123.bmp', 'LZP.69.bmp', 'LZP.244.bmp', 'LZP.126.bmp', 'LZP.99.bmp', 'LZP.193.bmp', 'LZP.103.bmp', 'LZP.166.bmp', 'LZP.230.bmp', 'LZP.181.bmp', 'LZP.165.bmp', 'LZP.81.bmp', 'LZP.84.bmp', 'LZP.215.bmp', 'LZP.139.bmp', 'LZP.213.bmp', 'LZP.192.bmp', 'LZP.200.bmp', 'LZP.195.bmp', 'LZP.88.bmp', 'LZP.122.bmp', 'LZP.160.bmp', 'LZP.228.bmp', 'LZP.171.bmp', 'LZP.186.bmp', 'LZP.222.bmp', 'LZP.68.bmp', 'LZP.30.bmp', 'LZP.45.bmp', 'LZP.250.bmp', 'LZP.158.bmp', 'LZP.36.bmp', 'LZP.70.bmp', 'LZP.62.bmp', 'LZP.114.bmp', 'LZP.106.bmp', 'LZP.110.bmp', 'LZP.89.bmp', 'LZP.48.bmp', 'LZP.42.bmp', 'LZP.113.bmp', 'LZP.24.bmp', 'LZP.28.bmp', 'LZP.180.bmp', 'LZP.153.bmp', 'LZP.95.bmp', 'LZP.145.bmp', 'LZP.98.bmp', 'LZP.38.bmp', 'LZP.20.bmp', 'LZP.136.bmp', 'LZP.18.bmp', 'LZP.168.bmp', 'LZP.155.bmp', 'LZP.209.bmp', 'LZP.127.bmp', 'LZP.256.bmp', 'LZP.9.bmp', 'LZP.205.bmp', 'LZP.258.bmp', 'LZP.57.bmp', 'LZP.40.bmp', 'LZP.128.bmp', 'LZP.248.bmp', 'LZP.214.bmp']\n",
      "66\n",
      "['LZP.254.bmp', 'LZP.262.bmp', 'LZP.120.bmp', 'LZP.111.bmp', 'LZP.115.bmp', 'LZP.140.bmp', 'LZP.170.bmp', 'LZP.80.bmp', 'LZP.261.bmp', 'LZP.197.bmp', 'LZP.93.bmp', 'LZP.137.bmp', 'LZP.226.bmp', 'LZP.49.bmp', 'LZP.223.bmp', 'LZP.60.bmp', 'LZP.1.bmp', 'LZP.149.bmp', 'LZP.241.bmp', 'LZP.96.bmp', 'LZP.157.bmp', 'LZP.112.bmp', 'LZP.61.bmp', 'LZP.239.bmp', 'LZP.196.bmp', 'LZP.229.bmp', 'LZP.34.bmp', 'LZP.242.bmp', 'LZP.169.bmp', 'LZP.77.bmp', 'LZP.175.bmp', 'LZP.44.bmp', 'LZP.116.bmp', 'LZP.67.bmp', 'LZP.172.bmp', 'LZP.211.bmp', 'LZP.72.bmp', 'LZP.240.bmp', 'LZP.97.bmp', 'LZP.90.bmp', 'LZP.154.bmp', 'LZP.35.bmp', 'LZP.220.bmp', 'LZP.107.bmp', 'LZP.11.bmp', 'LZP.92.bmp', 'LZP.190.bmp', 'LZP.245.bmp', 'LZP.243.bmp', 'LZP.63.bmp', 'LZP.19.bmp', 'LZP.83.bmp', 'LZP.125.bmp', 'LZP.133.bmp', 'LZP.8.bmp', 'LZP.41.bmp', 'LZP.207.bmp', 'LZP.167.bmp', 'LZP.142.bmp', 'LZP.251.bmp', 'LZP.236.bmp', 'LZP.105.bmp', 'LZP.7.bmp', 'LZP.247.bmp', 'LZP.219.bmp', 'LZP.16.bmp']\n",
      "407\n",
      "['LPZP.496.bmp', 'LPZP.300.bmp', 'LPZP.118.bmp', 'LPZP.149.bmp', 'LPZP.296.bmp', 'LPZP.75.bmp', 'LPZP.424.bmp', 'LPZP.464.bmp', 'LPZP.64.bmp', 'LPZP.62.bmp', 'LPZP.306.bmp', 'LPZP.206.bmp', 'LPZP.537.bmp', 'LPZP.17.bmp', 'LPZP.350.bmp', 'LPZP.46.bmp', 'LPZP.325.bmp', 'LPZP.63.bmp', 'LPZP.516.bmp', 'LPZP.249.bmp', 'LPZP.53.bmp', 'LPZP.455.bmp', 'LPZP.315.bmp', 'LPZP.70.bmp', 'LPZP.5.bmp', 'LPZP.401.bmp', 'LPZP.111.bmp', 'LPZP.14.bmp', 'LPZP.444.bmp', 'LPZP.58.bmp', 'LPZP.526.bmp', 'LPZP.407.bmp', 'LPZP.461.bmp', 'LPZP.204.bmp', 'LPZP.339.bmp', 'LPZP.129.bmp', 'LPZP.493.bmp', 'LPZP.135.bmp', 'LPZP.279.bmp', 'LPZP.354.bmp', 'LPZP.171.bmp', 'LPZP.11.bmp', 'LPZP.463.bmp', 'LPZP.241.bmp', 'LPZP.200.bmp', 'LPZP.0.bmp', 'LPZP.443.bmp', 'LPZP.280.bmp', 'LPZP.170.bmp', 'LPZP.392.bmp', 'LPZP.26.bmp', 'LPZP.38.bmp', 'LPZP.127.bmp', 'LPZP.34.bmp', 'LPZP.293.bmp', 'LPZP.484.bmp', 'LPZP.210.bmp', 'LPZP.353.bmp', 'LPZP.94.bmp', 'LPZP.52.bmp', 'LPZP.246.bmp', 'LPZP.272.bmp', 'LPZP.283.bmp', 'LPZP.449.bmp', 'LPZP.21.bmp', 'LPZP.261.bmp', 'LPZP.389.bmp', 'LPZP.82.bmp', 'LPZP.6.bmp', 'LPZP.379.bmp', 'LPZP.309.bmp', 'LPZP.372.bmp', 'LPZP.425.bmp', 'LPZP.235.bmp', 'LPZP.159.bmp', 'LPZP.362.bmp', 'LPZP.403.bmp', 'LPZP.67.bmp', 'LPZP.368.bmp', 'LPZP.105.bmp', 'LPZP.172.bmp', 'LPZP.356.bmp', 'LPZP.489.bmp', 'LPZP.472.bmp', 'LPZP.27.bmp', 'LPZP.74.bmp', 'LPZP.292.bmp', 'LPZP.447.bmp', 'LPZP.426.bmp', 'LPZP.258.bmp', 'LPZP.116.bmp', 'LPZP.65.bmp', 'LPZP.477.bmp', 'LPZP.29.bmp', 'LPZP.448.bmp', 'LPZP.406.bmp', 'LPZP.370.bmp', 'LPZP.20.bmp', 'LPZP.400.bmp', 'LPZP.380.bmp', 'LPZP.183.bmp', 'LPZP.193.bmp', 'LPZP.31.bmp', 'LPZP.487.bmp', 'LPZP.60.bmp', 'LPZP.365.bmp', 'LPZP.66.bmp', 'LPZP.474.bmp', 'LPZP.176.bmp', 'LPZP.138.bmp', 'LPZP.324.bmp', 'LPZP.504.bmp', 'LPZP.506.bmp', 'LPZP.189.bmp', 'LPZP.524.bmp', 'LPZP.128.bmp', 'LPZP.456.bmp', 'LPZP.192.bmp', 'LPZP.333.bmp', 'LPZP.412.bmp', 'LPZP.288.bmp', 'LPZP.393.bmp', 'LPZP.104.bmp', 'LPZP.480.bmp', 'LPZP.383.bmp', 'LPZP.152.bmp', 'LPZP.419.bmp', 'LPZP.251.bmp', 'LPZP.421.bmp', 'LPZP.523.bmp', 'LPZP.287.bmp', 'LPZP.181.bmp', 'LPZP.394.bmp', 'LPZP.386.bmp', 'LPZP.119.bmp', 'LPZP.103.bmp', 'LPZP.208.bmp', 'LPZP.469.bmp', 'LPZP.512.bmp', 'LPZP.173.bmp', 'LPZP.262.bmp', 'LPZP.19.bmp', 'LPZP.352.bmp', 'LPZP.194.bmp', 'LPZP.219.bmp', 'LPZP.373.bmp', 'LPZP.265.bmp', 'LPZP.161.bmp', 'LPZP.214.bmp', 'LPZP.408.bmp', 'LPZP.297.bmp', 'LPZP.231.bmp', 'LPZP.158.bmp', 'LPZP.462.bmp', 'LPZP.79.bmp', 'LPZP.201.bmp', 'LPZP.388.bmp', 'LPZP.182.bmp', 'LPZP.414.bmp', 'LPZP.96.bmp', 'LPZP.319.bmp', 'LPZP.92.bmp', 'LPZP.109.bmp', 'LPZP.242.bmp', 'LPZP.276.bmp', 'LPZP.162.bmp', 'LPZP.252.bmp', 'LPZP.374.bmp', 'LPZP.10.bmp', 'LPZP.39.bmp', 'LPZP.264.bmp', 'LPZP.110.bmp', 'LPZP.24.bmp', 'LPZP.378.bmp', 'LPZP.466.bmp', 'LPZP.117.bmp', 'LPZP.131.bmp', 'LPZP.143.bmp', 'LPZP.87.bmp', 'LPZP.108.bmp', 'LPZP.486.bmp', 'LPZP.44.bmp', 'LPZP.541.bmp', 'LPZP.188.bmp', 'LPZP.115.bmp', 'LPZP.314.bmp', 'LPZP.507.bmp', 'LPZP.180.bmp', 'LPZP.113.bmp', 'LPZP.263.bmp', 'LPZP.539.bmp', 'LPZP.514.bmp', 'LPZP.312.bmp', 'LPZP.491.bmp', 'LPZP.269.bmp', 'LPZP.422.bmp', 'LPZP.434.bmp', 'LPZP.346.bmp', 'LPZP.137.bmp', 'LPZP.185.bmp', 'LPZP.7.bmp', 'LPZP.471.bmp', 'LPZP.88.bmp', 'LPZP.411.bmp', 'LPZP.502.bmp', 'LPZP.30.bmp', 'LPZP.322.bmp', 'LPZP.366.bmp', 'LPZP.43.bmp', 'LPZP.435.bmp', 'LPZP.153.bmp', 'LPZP.453.bmp', 'LPZP.101.bmp', 'LPZP.323.bmp', 'LPZP.511.bmp', 'LPZP.9.bmp', 'LPZP.220.bmp', 'LPZP.470.bmp', 'LPZP.429.bmp', 'LPZP.358.bmp', 'LPZP.343.bmp', 'LPZP.331.bmp', 'LPZP.213.bmp', 'LPZP.197.bmp', 'LPZP.347.bmp', 'LPZP.260.bmp', 'LPZP.271.bmp', 'LPZP.133.bmp', 'LPZP.285.bmp', 'LPZP.147.bmp', 'LPZP.227.bmp', 'LPZP.291.bmp', 'LPZP.257.bmp', 'LPZP.51.bmp', 'LPZP.349.bmp', 'LPZP.4.bmp', 'LPZP.495.bmp', 'LPZP.340.bmp', 'LPZP.326.bmp', 'LPZP.360.bmp', 'LPZP.112.bmp', 'LPZP.361.bmp', 'LPZP.528.bmp', 'LPZP.317.bmp', 'LPZP.327.bmp', 'LPZP.243.bmp', 'LPZP.381.bmp', 'LPZP.190.bmp', 'LPZP.145.bmp', 'LPZP.56.bmp', 'LPZP.13.bmp', 'LPZP.239.bmp', 'LPZP.433.bmp', 'LPZP.202.bmp', 'LPZP.525.bmp', 'LPZP.48.bmp', 'LPZP.351.bmp', 'LPZP.270.bmp', 'LPZP.409.bmp', 'LPZP.95.bmp', 'LPZP.289.bmp', 'LPZP.536.bmp', 'LPZP.203.bmp', 'LPZP.37.bmp', 'LPZP.534.bmp', 'LPZP.428.bmp', 'LPZP.8.bmp', 'LPZP.156.bmp', 'LPZP.377.bmp', 'LPZP.382.bmp', 'LPZP.86.bmp', 'LPZP.282.bmp', 'LPZP.500.bmp', 'LPZP.42.bmp', 'LPZP.410.bmp', 'LPZP.330.bmp', 'LPZP.423.bmp', 'LPZP.404.bmp', 'LPZP.141.bmp', 'LPZP.295.bmp', 'LPZP.174.bmp', 'LPZP.458.bmp', 'LPZP.415.bmp', 'LPZP.417.bmp', 'LPZP.385.bmp', 'LPZP.402.bmp', 'LPZP.259.bmp', 'LPZP.150.bmp', 'LPZP.238.bmp', 'LPZP.144.bmp', 'LPZP.320.bmp', 'LPZP.303.bmp', 'LPZP.440.bmp', 'LPZP.328.bmp', 'LPZP.130.bmp', 'LPZP.391.bmp', 'LPZP.28.bmp', 'LPZP.337.bmp', 'LPZP.313.bmp', 'LPZP.533.bmp', 'LPZP.102.bmp', 'LPZP.195.bmp', 'LPZP.209.bmp', 'LPZP.217.bmp', 'LPZP.107.bmp', 'LPZP.3.bmp', 'LPZP.342.bmp', 'LPZP.186.bmp', 'LPZP.531.bmp', 'LPZP.441.bmp', 'LPZP.318.bmp', 'LPZP.535.bmp', 'LPZP.416.bmp', 'LPZP.387.bmp', 'LPZP.355.bmp', 'LPZP.237.bmp', 'LPZP.157.bmp', 'LPZP.498.bmp', 'LPZP.106.bmp', 'LPZP.218.bmp', 'LPZP.505.bmp', 'LPZP.302.bmp', 'LPZP.475.bmp', 'LPZP.93.bmp', 'LPZP.375.bmp', 'LPZP.98.bmp', 'LPZP.396.bmp', 'LPZP.304.bmp', 'LPZP.184.bmp', 'LPZP.72.bmp', 'LPZP.244.bmp', 'LPZP.83.bmp', 'LPZP.146.bmp', 'LPZP.54.bmp', 'LPZP.540.bmp', 'LPZP.305.bmp', 'LPZP.23.bmp', 'LPZP.527.bmp', 'LPZP.148.bmp', 'LPZP.126.bmp', 'LPZP.427.bmp', 'LPZP.151.bmp', 'LPZP.59.bmp', 'LPZP.12.bmp', 'LPZP.483.bmp', 'LPZP.321.bmp', 'LPZP.294.bmp', 'LPZP.301.bmp', 'LPZP.329.bmp', 'LPZP.100.bmp', 'LPZP.478.bmp', 'LPZP.446.bmp', 'LPZP.165.bmp', 'LPZP.121.bmp', 'LPZP.78.bmp', 'LPZP.445.bmp', 'LPZP.405.bmp', 'LPZP.436.bmp', 'LPZP.168.bmp', 'LPZP.216.bmp', 'LPZP.367.bmp', 'LPZP.357.bmp', 'LPZP.132.bmp', 'LPZP.175.bmp', 'LPZP.451.bmp', 'LPZP.485.bmp', 'LPZP.492.bmp', 'LPZP.234.bmp', 'LPZP.71.bmp', 'LPZP.248.bmp', 'LPZP.232.bmp', 'LPZP.311.bmp', 'LPZP.55.bmp', 'LPZP.530.bmp', 'LPZP.47.bmp', 'LPZP.179.bmp', 'LPZP.25.bmp', 'LPZP.490.bmp', 'LPZP.532.bmp', 'LPZP.224.bmp', 'LPZP.1.bmp', 'LPZP.479.bmp', 'LPZP.452.bmp', 'LPZP.50.bmp', 'LPZP.225.bmp', 'LPZP.286.bmp', 'LPZP.438.bmp', 'LPZP.359.bmp', 'LPZP.399.bmp', 'LPZP.198.bmp', 'LPZP.275.bmp', 'LPZP.454.bmp', 'LPZP.488.bmp', 'LPZP.277.bmp', 'LPZP.215.bmp', 'LPZP.69.bmp', 'LPZP.205.bmp', 'LPZP.236.bmp', 'LPZP.345.bmp', 'LPZP.250.bmp', 'LPZP.457.bmp', 'LPZP.32.bmp', 'LPZP.529.bmp', 'LPZP.308.bmp', 'LPZP.247.bmp', 'LPZP.266.bmp', 'LPZP.139.bmp']\n",
      "136\n",
      "['LPZP.520.bmp', 'LPZP.376.bmp', 'LPZP.123.bmp', 'LPZP.344.bmp', 'LPZP.253.bmp', 'LPZP.199.bmp', 'LPZP.81.bmp', 'LPZP.509.bmp', 'LPZP.207.bmp', 'LPZP.229.bmp', 'LPZP.134.bmp', 'LPZP.40.bmp', 'LPZP.124.bmp', 'LPZP.163.bmp', 'LPZP.169.bmp', 'LPZP.510.bmp', 'LPZP.364.bmp', 'LPZP.278.bmp', 'LPZP.508.bmp', 'LPZP.482.bmp', 'LPZP.222.bmp', 'LPZP.167.bmp', 'LPZP.177.bmp', 'LPZP.460.bmp', 'LPZP.513.bmp', 'LPZP.90.bmp', 'LPZP.398.bmp', 'LPZP.89.bmp', 'LPZP.420.bmp', 'LPZP.332.bmp', 'LPZP.338.bmp', 'LPZP.84.bmp', 'LPZP.476.bmp', 'LPZP.233.bmp', 'LPZP.515.bmp', 'LPZP.61.bmp', 'LPZP.442.bmp', 'LPZP.91.bmp', 'LPZP.267.bmp', 'LPZP.316.bmp', 'LPZP.73.bmp', 'LPZP.140.bmp', 'LPZP.348.bmp', 'LPZP.125.bmp', 'LPZP.228.bmp', 'LPZP.212.bmp', 'LPZP.221.bmp', 'LPZP.518.bmp', 'LPZP.97.bmp', 'LPZP.413.bmp', 'LPZP.85.bmp', 'LPZP.226.bmp', 'LPZP.49.bmp', 'LPZP.499.bmp', 'LPZP.397.bmp', 'LPZP.57.bmp', 'LPZP.468.bmp', 'LPZP.307.bmp', 'LPZP.191.bmp', 'LPZP.521.bmp', 'LPZP.196.bmp', 'LPZP.76.bmp', 'LPZP.41.bmp', 'LPZP.437.bmp', 'LPZP.273.bmp', 'LPZP.36.bmp', 'LPZP.336.bmp', 'LPZP.517.bmp', 'LPZP.418.bmp', 'LPZP.154.bmp', 'LPZP.254.bmp', 'LPZP.16.bmp', 'LPZP.18.bmp', 'LPZP.497.bmp', 'LPZP.538.bmp', 'LPZP.114.bmp', 'LPZP.522.bmp', 'LPZP.80.bmp', 'LPZP.256.bmp', 'LPZP.432.bmp', 'LPZP.166.bmp', 'LPZP.299.bmp', 'LPZP.334.bmp', 'LPZP.542.bmp', 'LPZP.240.bmp', 'LPZP.223.bmp', 'LPZP.230.bmp', 'LPZP.281.bmp', 'LPZP.341.bmp', 'LPZP.160.bmp', 'LPZP.122.bmp', 'LPZP.459.bmp', 'LPZP.395.bmp', 'LPZP.187.bmp', 'LPZP.274.bmp', 'LPZP.155.bmp', 'LPZP.465.bmp', 'LPZP.481.bmp', 'LPZP.99.bmp', 'LPZP.68.bmp', 'LPZP.120.bmp', 'LPZP.2.bmp', 'LPZP.298.bmp', 'LPZP.22.bmp', 'LPZP.384.bmp', 'LPZP.450.bmp', 'LPZP.245.bmp', 'LPZP.519.bmp', 'LPZP.136.bmp', 'LPZP.371.bmp', 'LPZP.310.bmp', 'LPZP.178.bmp', 'LPZP.467.bmp', 'LPZP.268.bmp', 'LPZP.290.bmp', 'LPZP.431.bmp', 'LPZP.390.bmp', 'LPZP.363.bmp', 'LPZP.142.bmp', 'LPZP.430.bmp', 'LPZP.45.bmp', 'LPZP.369.bmp', 'LPZP.255.bmp', 'LPZP.77.bmp', 'LPZP.335.bmp', 'LPZP.501.bmp', 'LPZP.35.bmp', 'LPZP.164.bmp', 'LPZP.284.bmp', 'LPZP.503.bmp', 'LPZP.473.bmp', 'LPZP.211.bmp', 'LPZP.15.bmp', 'LPZP.494.bmp', 'LPZP.439.bmp', 'LPZP.33.bmp']\n",
      "272\n",
      "['HESP.303.bmp', 'HESP.261.bmp', 'HESP.52.bmp', 'HESP.232.bmp', 'HESP.96.bmp', 'HESP.165.bmp', 'HESP.214.bmp', 'HESP.45.bmp', 'HESP.131.bmp', 'HESP.26.bmp', 'HESP.94.bmp', 'HESP.70.bmp', 'HESP.269.bmp', 'HESP.224.bmp', 'HESP.293.bmp', 'HESP.244.bmp', 'HESP.13.bmp', 'HESP.348.bmp', 'HESP.31.bmp', 'HESP.130.bmp', 'HESP.194.bmp', 'HESP.19.bmp', 'HESP.15.bmp', 'HESP.325.bmp', 'HESP.359.bmp', 'HESP.4.bmp', 'HESP.312.bmp', 'HESP.349.bmp', 'HESP.301.bmp', 'HESP.199.bmp', 'HESP.157.bmp', 'HESP.5.bmp', 'HESP.67.bmp', 'HESP.249.bmp', 'HESP.216.bmp', 'HESP.253.bmp', 'HESP.129.bmp', 'HESP.357.bmp', 'HESP.161.bmp', 'HESP.98.bmp', 'HESP.255.bmp', 'HESP.55.bmp', 'HESP.218.bmp', 'HESP.83.bmp', 'HESP.338.bmp', 'HESP.213.bmp', 'HESP.113.bmp', 'HESP.115.bmp', 'HESP.217.bmp', 'HESP.283.bmp', 'HESP.3.bmp', 'HESP.153.bmp', 'HESP.183.bmp', 'HESP.48.bmp', 'HESP.203.bmp', 'HESP.139.bmp', 'HESP.171.bmp', 'HESP.62.bmp', 'HESP.86.bmp', 'HESP.65.bmp', 'HESP.310.bmp', 'HESP.260.bmp', 'HESP.341.bmp', 'HESP.79.bmp', 'HESP.190.bmp', 'HESP.193.bmp', 'HESP.121.bmp', 'HESP.238.bmp', 'HESP.321.bmp', 'HESP.28.bmp', 'HESP.174.bmp', 'HESP.210.bmp', 'HESP.286.bmp', 'HESP.276.bmp', 'HESP.30.bmp', 'HESP.208.bmp', 'HESP.146.bmp', 'HESP.47.bmp', 'HESP.277.bmp', 'HESP.180.bmp', 'HESP.337.bmp', 'HESP.344.bmp', 'HESP.162.bmp', 'HESP.100.bmp', 'HESP.263.bmp', 'HESP.186.bmp', 'HESP.362.bmp', 'HESP.182.bmp', 'HESP.72.bmp', 'HESP.317.bmp', 'HESP.77.bmp', 'HESP.21.bmp', 'HESP.110.bmp', 'HESP.119.bmp', 'HESP.311.bmp', 'HESP.356.bmp', 'HESP.242.bmp', 'HESP.204.bmp', 'HESP.10.bmp', 'HESP.101.bmp', 'HESP.234.bmp', 'HESP.103.bmp', 'HESP.289.bmp', 'HESP.246.bmp', 'HESP.202.bmp', 'HESP.159.bmp', 'HESP.44.bmp', 'HESP.43.bmp', 'HESP.81.bmp', 'HESP.56.bmp', 'HESP.132.bmp', 'HESP.309.bmp', 'HESP.220.bmp', 'HESP.170.bmp', 'HESP.64.bmp', 'HESP.37.bmp', 'HESP.88.bmp', 'HESP.59.bmp', 'HESP.176.bmp', 'HESP.95.bmp', 'HESP.305.bmp', 'HESP.148.bmp', 'HESP.336.bmp', 'HESP.54.bmp', 'HESP.58.bmp', 'HESP.239.bmp', 'HESP.32.bmp', 'HESP.205.bmp', 'HESP.14.bmp', 'HESP.168.bmp', 'HESP.135.bmp', 'HESP.350.bmp', 'HESP.51.bmp', 'HESP.285.bmp', 'HESP.104.bmp', 'HESP.144.bmp', 'HESP.141.bmp', 'HESP.1.bmp', 'HESP.173.bmp', 'HESP.93.bmp', 'HESP.320.bmp', 'HESP.227.bmp', 'HESP.353.bmp', 'HESP.197.bmp', 'HESP.291.bmp', 'HESP.316.bmp', 'HESP.243.bmp', 'HESP.78.bmp', 'HESP.24.bmp', 'HESP.53.bmp', 'HESP.109.bmp', 'HESP.156.bmp', 'HESP.151.bmp', 'HESP.20.bmp', 'HESP.46.bmp', 'HESP.209.bmp', 'HESP.288.bmp', 'HESP.231.bmp', 'HESP.189.bmp', 'HESP.92.bmp', 'HESP.297.bmp', 'HESP.339.bmp', 'HESP.358.bmp', 'HESP.278.bmp', 'HESP.206.bmp', 'HESP.279.bmp', 'HESP.152.bmp', 'HESP.11.bmp', 'HESP.262.bmp', 'HESP.74.bmp', 'HESP.63.bmp', 'HESP.200.bmp', 'HESP.75.bmp', 'HESP.29.bmp', 'HESP.6.bmp', 'HESP.302.bmp', 'HESP.326.bmp', 'HESP.147.bmp', 'HESP.150.bmp', 'HESP.164.bmp', 'HESP.50.bmp', 'HESP.175.bmp', 'HESP.8.bmp', 'HESP.158.bmp', 'HESP.351.bmp', 'HESP.60.bmp', 'HESP.39.bmp', 'HESP.268.bmp', 'HESP.241.bmp', 'HESP.307.bmp', 'HESP.271.bmp', 'HESP.108.bmp', 'HESP.201.bmp', 'HESP.284.bmp', 'HESP.66.bmp', 'HESP.331.bmp', 'HESP.87.bmp', 'HESP.264.bmp', 'HESP.128.bmp', 'HESP.198.bmp', 'HESP.111.bmp', 'HESP.117.bmp', 'HESP.35.bmp', 'HESP.259.bmp', 'HESP.116.bmp', 'HESP.318.bmp', 'HESP.27.bmp', 'HESP.346.bmp', 'HESP.23.bmp', 'HESP.287.bmp', 'HESP.12.bmp', 'HESP.237.bmp', 'HESP.327.bmp', 'HESP.360.bmp', 'HESP.0.bmp', 'HESP.9.bmp', 'HESP.282.bmp', 'HESP.106.bmp', 'HESP.25.bmp', 'HESP.112.bmp', 'HESP.143.bmp', 'HESP.355.bmp', 'HESP.179.bmp', 'HESP.354.bmp', 'HESP.252.bmp', 'HESP.137.bmp', 'HESP.270.bmp', 'HESP.340.bmp', 'HESP.138.bmp', 'HESP.107.bmp', 'HESP.34.bmp', 'HESP.102.bmp', 'HESP.306.bmp', 'HESP.118.bmp', 'HESP.248.bmp', 'HESP.280.bmp', 'HESP.42.bmp', 'HESP.300.bmp', 'HESP.345.bmp', 'HESP.272.bmp', 'HESP.123.bmp', 'HESP.133.bmp', 'HESP.69.bmp', 'HESP.296.bmp', 'HESP.257.bmp', 'HESP.188.bmp', 'HESP.275.bmp', 'HESP.313.bmp', 'HESP.172.bmp', 'HESP.126.bmp', 'HESP.265.bmp', 'HESP.235.bmp', 'HESP.319.bmp', 'HESP.258.bmp', 'HESP.149.bmp', 'HESP.207.bmp', 'HESP.229.bmp', 'HESP.335.bmp', 'HESP.40.bmp', 'HESP.124.bmp', 'HESP.163.bmp', 'HESP.169.bmp', 'HESP.324.bmp', 'HESP.322.bmp', 'HESP.304.bmp', 'HESP.222.bmp', 'HESP.347.bmp', 'HESP.177.bmp', 'HESP.245.bmp', 'HESP.90.bmp', 'HESP.333.bmp', 'HESP.84.bmp']\n",
      "91\n",
      "['HESP.323.bmp', 'HESP.329.bmp', 'HESP.136.bmp', 'HESP.61.bmp', 'HESP.91.bmp', 'HESP.267.bmp', 'HESP.73.bmp', 'HESP.140.bmp', 'HESP.125.bmp', 'HESP.228.bmp', 'HESP.212.bmp', 'HESP.221.bmp', 'HESP.178.bmp', 'HESP.97.bmp', 'HESP.85.bmp', 'HESP.226.bmp', 'HESP.49.bmp', 'HESP.57.bmp', 'HESP.294.bmp', 'HESP.191.bmp', 'HESP.290.bmp', 'HESP.196.bmp', 'HESP.76.bmp', 'HESP.41.bmp', 'HESP.273.bmp', 'HESP.36.bmp', 'HESP.154.bmp', 'HESP.254.bmp', 'HESP.361.bmp', 'HESP.18.bmp', 'HESP.315.bmp', 'HESP.211.bmp', 'HESP.114.bmp', 'HESP.80.bmp', 'HESP.256.bmp', 'HESP.166.bmp', 'HESP.299.bmp', 'HESP.33.bmp', 'HESP.240.bmp', 'HESP.223.bmp', 'HESP.230.bmp', 'HESP.281.bmp', 'HESP.160.bmp', 'HESP.328.bmp', 'HESP.187.bmp', 'HESP.274.bmp', 'HESP.332.bmp', 'HESP.99.bmp', 'HESP.330.bmp', 'HESP.120.bmp', 'HESP.2.bmp', 'HESP.298.bmp', 'HESP.343.bmp', 'HESP.192.bmp', 'HESP.314.bmp', 'HESP.225.bmp', 'HESP.122.bmp', 'HESP.352.bmp', 'HESP.68.bmp', 'HESP.185.bmp', 'HESP.155.bmp', 'HESP.89.bmp', 'HESP.233.bmp', 'HESP.134.bmp', 'HESP.145.bmp', 'HESP.342.bmp', 'HESP.195.bmp', 'HESP.181.bmp', 'HESP.308.bmp', 'HESP.71.bmp', 'HESP.215.bmp', 'HESP.22.bmp', 'HESP.184.bmp', 'HESP.127.bmp', 'HESP.38.bmp', 'HESP.167.bmp', 'HESP.250.bmp', 'HESP.266.bmp', 'HESP.17.bmp', 'HESP.82.bmp', 'HESP.334.bmp', 'HESP.142.bmp', 'HESP.251.bmp', 'HESP.236.bmp', 'HESP.105.bmp', 'HESP.7.bmp', 'HESP.295.bmp', 'HESP.247.bmp', 'HESP.219.bmp', 'HESP.16.bmp', 'HESP.292.bmp']\n",
      "63\n",
      "['CFP.6.bmp', 'CFP.68.bmp', 'CFP.60.bmp', 'CFP.78.bmp', 'CFP.50.bmp', 'CFP.33.bmp', 'CFP.3.bmp', 'CFP.25.bmp', 'CFP.51.bmp', 'CFP.36.bmp', 'CFP.57.bmp', 'CFP.75.bmp', 'CFP.67.bmp', 'CFP.71.bmp', 'CFP.45.bmp', 'CFP.30.bmp', 'CFP.77.bmp', 'CFP.34.bmp', 'CFP.27.bmp', 'CFP.7.bmp', 'CFP.64.bmp', 'CFP.63.bmp', 'CFP.10.bmp', 'CFP.56.bmp', 'CFP.70.bmp', 'CFP.40.bmp', 'CFP.32.bmp', 'CFP.13.bmp', 'CFP.14.bmp', 'CFP.17.bmp', 'CFP.21.bmp', 'CFP.72.bmp', 'CFP.48.bmp', 'CFP.47.bmp', 'CFP.49.bmp', 'CFP.12.bmp', 'CFP.65.bmp', 'CFP.44.bmp', 'CFP.0.bmp', 'CFP.37.bmp', 'CFP.2.bmp', 'CFP.58.bmp', 'CFP.39.bmp', 'CFP.28.bmp', 'CFP.15.bmp', 'CFP.69.bmp', 'CFP.79.bmp', 'CFP.23.bmp', 'CFP.42.bmp', 'CFP.19.bmp', 'CFP.80.bmp', 'CFP.11.bmp', 'CFP.29.bmp', 'CFP.16.bmp', 'CFP.43.bmp', 'CFP.52.bmp', 'CFP.18.bmp', 'CFP.76.bmp', 'CFP.24.bmp', 'CFP.22.bmp', 'CFP.38.bmp', 'CFP.8.bmp', 'CFP.55.bmp']\n",
      "20\n",
      "['CFP.53.bmp', 'CFP.5.bmp', 'CFP.46.bmp', 'CFP.31.bmp', 'CFP.9.bmp', 'CFP.41.bmp', 'CFP.74.bmp', 'CFP.66.bmp', 'CFP.81.bmp', 'CFP.20.bmp', 'CFP.35.bmp', 'CFP.62.bmp', 'CFP.59.bmp', 'CFP.26.bmp', 'CFP.1.bmp', 'CFP.82.bmp', 'CFP.61.bmp', 'CFP.54.bmp', 'CFP.4.bmp', 'CFP.73.bmp']\n"
     ]
    }
   ],
   "source": [
    "#USE THIS ONE\n",
    "\n",
    "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
    "# randomize order of image locations\n",
    "# this will help model in not being data sequence dependent\n",
    "\n",
    "# Copy first CM images to train_lion_dir\n",
    "import random\n",
    "\n",
    "fnames = ['LZP.{}.bmp'.format(i) for i in range(263)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:197]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_lion_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "\n",
    "# Copy next CM images to validation_lion_dir\n",
    "fnamesv = fnames[197:263]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_lion_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "    \n",
    "    \n",
    "\n",
    "# Copy first TM images to train_leop_dir # \n",
    "fnames = ['LPZP.{}.bmp'.format(i) for i in range(543)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:407]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_leop_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next 10 TM images to validation_leop_dir\n",
    "fnamesv = fnames[407:543]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_leop_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "         \n",
    "        \n",
    "    \n",
    "# Copy first TM images to train_hyena_dir # \n",
    "fnames = ['HESP.{}.bmp'.format(i) for i in range(363)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:272]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_hyena_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next 10 TM images to validation_hip_dir\n",
    "fnamesv = fnames[272:363]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_hyena_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "\n",
    "    \n",
    "\n",
    "# Copy first TM images to train_croc_dir # \n",
    "fnames = ['CFP.{}.bmp'.format(i) for i in range(83)]\n",
    "random.seed(10)\n",
    "random.shuffle(fnames)\n",
    "fnamest = fnames[0:63]\n",
    "print(len(fnamest))\n",
    "print(fnamest)\n",
    "\n",
    "for fname in fnamest:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(train_croc_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "        \n",
    "# Copy next 10 TM images to validation_red_dir\n",
    "fnamesv = fnames[63:83]\n",
    "print(len(fnamesv))\n",
    "print(fnamesv)\n",
    "for fname in fnamesv:\n",
    "    src = os.path.join(original_dir, fname)\n",
    "    dst = os.path.join(validation_croc_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "efe09e3f",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#training and testing sets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "02b116cf",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "italic-substance",
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.applications.densenet import preprocess_input#DENSENET201\n",
    "from keras.applications.resnet50 import preprocess_input#RESNET50\n",
    "from keras.applications.inception_resnet_v2 import preprocess_input #InceptionResNetV2 \n",
    "from keras.applications.nasnet import preprocess_input #NASNetLarge\n",
    "from keras.applications.inception_v3 import preprocess_input #InceptionV3\n",
    "from keras.applications.vgg19 import preprocess_input #VGG19\n",
    "from keras.applications.vgg16 import preprocess_input #VGG16\n",
    "from keras.applications.imagenet_utils import decode_predictions, preprocess_input#for efficient Net"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0b730d9a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 939 images belonging to 4 classes.\n",
      "Found 313 images belonging to 4 classes.\n"
     ]
    }
   ],
   "source": [
    "from tensorflow.keras.applications.densenet import preprocess_input #for RESNET 50\n",
    "#from keras.applications.imagenet_utils import decode_predictions, preprocess_input#for efficient Net\n",
    "\n",
    "#Let's train our network using data augmentation and dropout:\n",
    "train_datagen = ImageDataGenerator(\n",
    "    rotation_range=40,\n",
    "    width_shift_range=0.2,\n",
    "    height_shift_range=0.2,\n",
    "    shear_range=0.2,\n",
    "    zoom_range=0.2,\n",
    "    horizontal_flip=True,\n",
    "    preprocessing_function= \\\n",
    "    keras.applications.densenet.preprocess_input)#OJO!!!! imagenet_utils for Efficient Net\n",
    "\n",
    "# Note that the validation data should not be augmented!\n",
    "test_datagen = ImageDataGenerator(preprocessing_function= \\\n",
    "    keras.applications.densenet.preprocess_input)#OJO!!!\n",
    "\n",
    "train_generator = train_datagen.flow_from_directory(\n",
    "        # This is the target directory\n",
    "        train_dir,\n",
    "        # All images will be resized \n",
    "        target_size=(250, 200),\n",
    "        batch_size=32,\n",
    "        class_mode='categorical')#put \"categorical\" si son más de 2 categorías\n",
    "\n",
    "validation_generator = test_datagen.flow_from_directory(\n",
    "        validation_dir,\n",
    "        target_size=(250, 200),\n",
    "        batch_size=20,\n",
    "        class_mode='categorical',\n",
    "        shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "toxic-compact",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(32, 250, 200, 3) train samples\n",
      "(20, 250, 200, 3) test samples\n"
     ]
    }
   ],
   "source": [
    "x_tr, y_tr = next(train_generator)\n",
    "x_t, y_t = next(validation_generator)\n",
    "print(x_tr.shape, 'train samples')\n",
    "print(x_t.shape, 'test samples')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "original-above",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 939 images belonging to 4 classes.\n",
      "Found 313 images belonging to 4 classes.\n",
      "(939, 250, 200, 3) train samples\n",
      "(313, 250, 200, 3) test samples\n"
     ]
    }
   ],
   "source": [
    "datagenTrain=train_datagen.flow_from_directory(\n",
    "        # This is the target directory\n",
    "        train_dir,\n",
    "        # All images will be resized to 40x160\n",
    "        target_size=(250,200),\n",
    "        batch_size=939,\n",
    "        # Since we use binary_crossentropy loss, we need binary labels\n",
    "        class_mode='categorical')\n",
    "datagenTest=test_datagen.flow_from_directory(\n",
    "        # This is the target directory\n",
    "        validation_dir,\n",
    "        # All images will be resized to 40x160\n",
    "        target_size=(250, 200),\n",
    "        batch_size=313,\n",
    "        # Since we use binary_crossentropy loss, we need binary labels\n",
    "        class_mode='categorical',\n",
    "        shuffle=False)\n",
    "x_train, y_train = next(datagenTrain)\n",
    "x_test, y_test = next(datagenTest)\n",
    "print(x_train.shape, 'train samples')\n",
    "print(x_test.shape, 'test samples')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "62521d75",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "af7b5cdc",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#MODULE 2: CHOOSE MODEL"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d1d0fac",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "8d27b34c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# VGG19 for transfer learning \n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.vgg19 import VGG19\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = VGG19(include_top=False, input_shape=(120, 100, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\toutput = Dense(5, activation='softmax')(class1)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(lr=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "99d2acb6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/densenet/densenet201_weights_tf_dim_ordering_tf_kernels_notop.h5\n",
      "74836368/74836368 [==============================] - 1s 0us/step\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\md78\\Anaconda3\\lib\\site-packages\\keras\\optimizers\\optimizer_v2\\gradient_descent.py:108: UserWarning: The `lr` argument is deprecated, use `learning_rate` instead.\n",
      "  super(SGD, self).__init__(name, **kwargs)\n"
     ]
    }
   ],
   "source": [
    "# for transfer learning DenseNet201\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from keras.applications.densenet import DenseNet201\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "from keras.applications.densenet import DenseNet201, preprocess_input\n",
    "from keras.applications.densenet import preprocess_input\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = DenseNet201(include_top=False, input_shape=(120, 100, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\toutput = Dense(5, activation='softmax')(class1)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(lr=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "0359dccc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for transfer learning RESNET50\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.resnet50 import ResNet50\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = ResNet50(include_top=False, input_shape=(120, 100, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\toutput = Dense(5, activation='softmax')(class1)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(learning_rate=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "73b55816",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://storage.googleapis.com/keras-applications/efficientnetb7_notop.h5\n",
      "258076736/258076736 [==============================] - 3s 0us/step\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\md78\\Anaconda3\\lib\\site-packages\\keras\\optimizers\\optimizer_v2\\gradient_descent.py:108: UserWarning: The `lr` argument is deprecated, use `learning_rate` instead.\n",
      "  super(SGD, self).__init__(name, **kwargs)\n"
     ]
    }
   ],
   "source": [
    "# for transfer learning EfficientNetB7\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications import EfficientNetB7\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = EfficientNetB7(include_top=False, input_shape=(120, 100, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\toutput = Dense(5, activation='softmax')(class1)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(lr=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b20ad77",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ece230f",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "566a8bbd",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#activate Dropout and Early Stopping"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ece170ec",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Vgg19 for transfer learning with Dropout\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.vgg19 import VGG19\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = VGG19(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(lr=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e2158051",
   "metadata": {},
   "outputs": [],
   "source": [
    "# VGG19 for transfer learning with Dropout and Early Stopping\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.vgg19 import VGG19\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "from keras.callbacks import ModelCheckpoint, EarlyStopping\n",
    "\n",
    "\n",
    "#es=EarlyStopping(monitor=\"val_loss\", mode=\"min\", verbose=1)\n",
    "es=EarlyStopping(monitor=\"val_accuracy\", mode=\"max\", patience=15, verbose=1)\n",
    "mc=ModelCheckpoint(\"best_model1.h5\", monitor=\"val_accuracy\", mode=\"max\", verbose=1,save_best_only=True)\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = VGG19(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(6, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(learning_rate=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21114903",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "complicated-college",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for transfer learning RESNET50 with Dropout\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.resnet50 import ResNet50\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = ResNet50(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(lr=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "synthetic-macedonia",
   "metadata": {},
   "outputs": [],
   "source": [
    "# For adding new activation function\n",
    "from keras.layers import Activation\n",
    "from keras import backend as K\n",
    "from keras.utils.generic_utils import get_custom_objects\n",
    "def swish(x):\n",
    "    return (K.sigmoid(x) * x)\n",
    "\n",
    "get_custom_objects().update({'swish': Activation(swish)})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "716e2e60",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for transfer learning RESNET50 with Dropout\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.vgg19 import VGG19\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.optimizers import Adagrad\n",
    "from keras.optimizers import Adam\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "from tensorflow.keras.applications import EfficientNetB7\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = EfficientNetB7(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='swish', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = Adagrad(lr=0.001)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4846573f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for transfer learning RESNET50 with Dropout and Early Stopping\n",
    "\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.resnet50 import ResNet50\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.callbacks import ModelCheckpoint, EarlyStopping\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "#es=EarlyStopping(monitor=\"val_loss\", mode=\"min\", verbose=1)\n",
    "es=EarlyStopping(monitor=\"val_accuracy\", mode=\"max\", patience=15, verbose=1)\n",
    "mc=ModelCheckpoint(\"best_model2.h5\", monitor=\"val_accuracy\", mode=\"max\", verbose=1,save_best_only=True)\n",
    "\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = ResNet50(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.2)(class1)\n",
    "\toutput = Dense(5, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(learning_rate=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50a09b9a",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "82c7ff2b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for transfer learning EfficientNetB7 with Dropout\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications import EfficientNetB7\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "from keras.layers import Dropout\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = EfficientNetB7(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(lr=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99b22969",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# for transfer learning EfficientNet7 with Dropout and Early Stopping\n",
    "\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications import EfficientNetB7\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.callbacks import ModelCheckpoint, EarlyStopping\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "#es=EarlyStopping(monitor=\"val_loss\", mode=\"min\", verbose=1)\n",
    "es=EarlyStopping(monitor=\"val_accuracy\", mode=\"max\", patience=15, verbose=1)\n",
    "mc=ModelCheckpoint(\"best_model2.h5\", monitor=\"val_accuracy\", mode=\"max\", verbose=1,save_best_only=True)\n",
    "\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = EfficientNetB7(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.2)(class1)\n",
    "\toutput = Dense(6, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(learning_rate=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "be5f7ef8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for transfer learning DENSENET with Dropout\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.densenet import DenseNet201\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.optimizers import SGD\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = DenseNet201(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = SGD(lr=0.001, momentum=0.9)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "e1b0d8a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for transfer learning RESNET50 with Dropout\n",
    "import sys\n",
    "from matplotlib import pyplot\n",
    "from tensorflow.keras.applications.densenet import DenseNet201\n",
    "from keras.models import Model\n",
    "from keras.layers import Dense\n",
    "from keras.layers import Flatten\n",
    "from keras.layers import Dropout\n",
    "from keras.optimizers import Adagrad\n",
    "from keras.optimizers import Adam\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "\n",
    "# define cnn model\n",
    "def define_model():\n",
    "\t# load model\n",
    "\tmodel = DenseNet201(include_top=False, input_shape=(250, 200, 3))\n",
    "\t# mark loaded layers as not trainable\n",
    "\tfor layer in model.layers:\n",
    "\t\tlayer.trainable = False\n",
    "\t# add new classifier layers\n",
    "\tflat1 = Flatten()(model.layers[-1].output)\n",
    "\tclass1 = Dense(128, activation='swish', kernel_initializer='he_uniform')(flat1)\n",
    "\tdrop=Dropout(0.3)(class1)\n",
    "\toutput = Dense(4, activation='softmax')(drop)\n",
    "\t# define new model\n",
    "\tmodel = Model(inputs=model.inputs, outputs=output)\n",
    "\t# compile model\n",
    "\topt = Adagrad(lr=0.001)\n",
    "\tmodel.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n",
    "\treturn model\n",
    "\n",
    "# define model\n",
    "model = define_model()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "703e6c3c",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6fc143a8",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#RUN MODEL:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "f73ae474",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\IDEA\\Anaconda3\\envs\\gputest\\lib\\site-packages\\tensorflow\\python\\keras\\engine\\training.py:1844: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators.\n",
      "  warnings.warn('`Model.fit_generator` is deprecated and '\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100\n",
      "30/30 [==============================] - 63s 2s/step - loss: 2.9741 - accuracy: 0.3969 - val_loss: 0.8376 - val_accuracy: 0.6533\n",
      "Epoch 2/100\n",
      "30/30 [==============================] - 45s 2s/step - loss: 0.8816 - accuracy: 0.6384 - val_loss: 0.6334 - val_accuracy: 0.7533\n",
      "Epoch 3/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.6786 - accuracy: 0.7226 - val_loss: 0.5975 - val_accuracy: 0.7367\n",
      "Epoch 4/100\n",
      "30/30 [==============================] - 45s 2s/step - loss: 0.6155 - accuracy: 0.7330 - val_loss: 0.5329 - val_accuracy: 0.7533\n",
      "Epoch 5/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.6079 - accuracy: 0.7713 - val_loss: 0.5400 - val_accuracy: 0.7833\n",
      "Epoch 6/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.5185 - accuracy: 0.7959 - val_loss: 0.5110 - val_accuracy: 0.7867\n",
      "Epoch 7/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.5035 - accuracy: 0.7911 - val_loss: 0.4961 - val_accuracy: 0.7833\n",
      "Epoch 8/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.4982 - accuracy: 0.7958 - val_loss: 0.4994 - val_accuracy: 0.7767\n",
      "Epoch 9/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.5044 - accuracy: 0.7984 - val_loss: 0.4676 - val_accuracy: 0.7867\n",
      "Epoch 10/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.4692 - accuracy: 0.8121 - val_loss: 0.4688 - val_accuracy: 0.7867\n",
      "Epoch 11/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.4220 - accuracy: 0.8310 - val_loss: 0.4567 - val_accuracy: 0.7900\n",
      "Epoch 12/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.4251 - accuracy: 0.8454 - val_loss: 0.4555 - val_accuracy: 0.8067\n",
      "Epoch 13/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.4734 - accuracy: 0.8112 - val_loss: 0.4434 - val_accuracy: 0.8033\n",
      "Epoch 14/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3984 - accuracy: 0.8400 - val_loss: 0.4419 - val_accuracy: 0.8133\n",
      "Epoch 15/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.4329 - accuracy: 0.8269 - val_loss: 0.4388 - val_accuracy: 0.8000\n",
      "Epoch 16/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3878 - accuracy: 0.8459 - val_loss: 0.4175 - val_accuracy: 0.8167\n",
      "Epoch 17/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.4257 - accuracy: 0.8175 - val_loss: 0.4209 - val_accuracy: 0.8133\n",
      "Epoch 18/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3706 - accuracy: 0.8468 - val_loss: 0.4223 - val_accuracy: 0.8233\n",
      "Epoch 19/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3976 - accuracy: 0.8305 - val_loss: 0.4190 - val_accuracy: 0.8300\n",
      "Epoch 20/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3900 - accuracy: 0.8438 - val_loss: 0.4036 - val_accuracy: 0.8233\n",
      "Epoch 21/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3383 - accuracy: 0.8646 - val_loss: 0.4110 - val_accuracy: 0.8267\n",
      "Epoch 22/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.4066 - accuracy: 0.8359 - val_loss: 0.4205 - val_accuracy: 0.8300\n",
      "Epoch 23/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3479 - accuracy: 0.8548 - val_loss: 0.4181 - val_accuracy: 0.8233\n",
      "Epoch 24/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3302 - accuracy: 0.8672 - val_loss: 0.4165 - val_accuracy: 0.8300\n",
      "Epoch 25/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.3360 - accuracy: 0.8695 - val_loss: 0.4726 - val_accuracy: 0.8067\n",
      "Epoch 26/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3187 - accuracy: 0.8747 - val_loss: 0.4481 - val_accuracy: 0.8033\n",
      "Epoch 27/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3004 - accuracy: 0.8819 - val_loss: 0.4264 - val_accuracy: 0.8133\n",
      "Epoch 28/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3699 - accuracy: 0.8642 - val_loss: 0.4202 - val_accuracy: 0.8333\n",
      "Epoch 29/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3098 - accuracy: 0.8802 - val_loss: 0.4282 - val_accuracy: 0.8167\n",
      "Epoch 30/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3265 - accuracy: 0.8559 - val_loss: 0.3995 - val_accuracy: 0.8167\n",
      "Epoch 31/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3403 - accuracy: 0.8744 - val_loss: 0.4157 - val_accuracy: 0.8233\n",
      "Epoch 32/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3044 - accuracy: 0.8819 - val_loss: 0.4104 - val_accuracy: 0.8233\n",
      "Epoch 33/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.3418 - accuracy: 0.8701 - val_loss: 0.4035 - val_accuracy: 0.8200\n",
      "Epoch 34/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3416 - accuracy: 0.8647 - val_loss: 0.4154 - val_accuracy: 0.8267\n",
      "Epoch 35/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3046 - accuracy: 0.8784 - val_loss: 0.4070 - val_accuracy: 0.8200\n",
      "Epoch 36/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3073 - accuracy: 0.8754 - val_loss: 0.4103 - val_accuracy: 0.8267\n",
      "Epoch 37/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3097 - accuracy: 0.8892 - val_loss: 0.3951 - val_accuracy: 0.8300\n",
      "Epoch 38/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2845 - accuracy: 0.9082 - val_loss: 0.4015 - val_accuracy: 0.8233\n",
      "Epoch 39/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2923 - accuracy: 0.8881 - val_loss: 0.4003 - val_accuracy: 0.8200\n",
      "Epoch 40/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2907 - accuracy: 0.8933 - val_loss: 0.3807 - val_accuracy: 0.8333\n",
      "Epoch 41/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2872 - accuracy: 0.8988 - val_loss: 0.4026 - val_accuracy: 0.8300\n",
      "Epoch 42/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.3049 - accuracy: 0.8840 - val_loss: 0.3782 - val_accuracy: 0.8467\n",
      "Epoch 43/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2794 - accuracy: 0.8919 - val_loss: 0.3972 - val_accuracy: 0.8233\n",
      "Epoch 44/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2915 - accuracy: 0.9033 - val_loss: 0.3763 - val_accuracy: 0.8300\n",
      "Epoch 45/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2645 - accuracy: 0.9068 - val_loss: 0.3815 - val_accuracy: 0.8267\n",
      "Epoch 46/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2849 - accuracy: 0.8935 - val_loss: 0.3889 - val_accuracy: 0.8367\n",
      "Epoch 47/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2712 - accuracy: 0.8919 - val_loss: 0.3728 - val_accuracy: 0.8233\n",
      "Epoch 48/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2652 - accuracy: 0.8969 - val_loss: 0.4092 - val_accuracy: 0.8100\n",
      "Epoch 49/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2418 - accuracy: 0.9098 - val_loss: 0.3926 - val_accuracy: 0.8400\n",
      "Epoch 50/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2527 - accuracy: 0.9019 - val_loss: 0.3863 - val_accuracy: 0.8400\n",
      "Epoch 51/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2511 - accuracy: 0.9102 - val_loss: 0.3880 - val_accuracy: 0.8300\n",
      "Epoch 52/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2386 - accuracy: 0.9121 - val_loss: 0.3887 - val_accuracy: 0.8400\n",
      "Epoch 53/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2772 - accuracy: 0.8911 - val_loss: 0.3996 - val_accuracy: 0.8333\n",
      "Epoch 54/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2571 - accuracy: 0.9171 - val_loss: 0.4071 - val_accuracy: 0.8300\n",
      "Epoch 55/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2648 - accuracy: 0.8938 - val_loss: 0.4145 - val_accuracy: 0.8233\n",
      "Epoch 56/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2424 - accuracy: 0.9255 - val_loss: 0.3868 - val_accuracy: 0.8400\n",
      "Epoch 57/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2801 - accuracy: 0.9063 - val_loss: 0.3851 - val_accuracy: 0.8400\n",
      "Epoch 58/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2128 - accuracy: 0.9286 - val_loss: 0.3769 - val_accuracy: 0.8400\n",
      "Epoch 59/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2581 - accuracy: 0.9127 - val_loss: 0.3929 - val_accuracy: 0.8433\n",
      "Epoch 60/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2485 - accuracy: 0.9019 - val_loss: 0.3981 - val_accuracy: 0.8333\n",
      "Epoch 61/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2351 - accuracy: 0.9245 - val_loss: 0.4091 - val_accuracy: 0.8367\n",
      "Epoch 62/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2738 - accuracy: 0.8986 - val_loss: 0.3871 - val_accuracy: 0.8333\n",
      "Epoch 63/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2463 - accuracy: 0.9087 - val_loss: 0.3851 - val_accuracy: 0.8333\n",
      "Epoch 64/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2162 - accuracy: 0.9198 - val_loss: 0.4018 - val_accuracy: 0.8167\n",
      "Epoch 65/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2170 - accuracy: 0.9222 - val_loss: 0.3651 - val_accuracy: 0.8467\n",
      "Epoch 66/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2364 - accuracy: 0.9141 - val_loss: 0.4021 - val_accuracy: 0.8167\n",
      "Epoch 67/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2356 - accuracy: 0.9149 - val_loss: 0.3769 - val_accuracy: 0.8433\n",
      "Epoch 68/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2329 - accuracy: 0.9123 - val_loss: 0.3727 - val_accuracy: 0.8400\n",
      "Epoch 69/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2364 - accuracy: 0.9018 - val_loss: 0.3667 - val_accuracy: 0.8333\n",
      "Epoch 70/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.1926 - accuracy: 0.9326 - val_loss: 0.4053 - val_accuracy: 0.8200\n",
      "Epoch 71/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2301 - accuracy: 0.9233 - val_loss: 0.3839 - val_accuracy: 0.8400\n",
      "Epoch 72/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2575 - accuracy: 0.9060 - val_loss: 0.3846 - val_accuracy: 0.8300\n",
      "Epoch 73/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2310 - accuracy: 0.9103 - val_loss: 0.3984 - val_accuracy: 0.8167\n",
      "Epoch 74/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2119 - accuracy: 0.9284 - val_loss: 0.4009 - val_accuracy: 0.8267\n",
      "Epoch 75/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2148 - accuracy: 0.9268 - val_loss: 0.4070 - val_accuracy: 0.8167\n",
      "Epoch 76/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2529 - accuracy: 0.8931 - val_loss: 0.4079 - val_accuracy: 0.8167\n",
      "Epoch 77/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2371 - accuracy: 0.9199 - val_loss: 0.3738 - val_accuracy: 0.8233\n",
      "Epoch 78/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2184 - accuracy: 0.9198 - val_loss: 0.3938 - val_accuracy: 0.8200\n",
      "Epoch 79/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2139 - accuracy: 0.9179 - val_loss: 0.3790 - val_accuracy: 0.8333\n",
      "Epoch 80/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2278 - accuracy: 0.9085 - val_loss: 0.3819 - val_accuracy: 0.8367\n",
      "Epoch 81/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2359 - accuracy: 0.9085 - val_loss: 0.3927 - val_accuracy: 0.8167\n",
      "Epoch 82/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2163 - accuracy: 0.9322 - val_loss: 0.3679 - val_accuracy: 0.8500\n",
      "Epoch 83/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2097 - accuracy: 0.9318 - val_loss: 0.3996 - val_accuracy: 0.8233\n",
      "Epoch 84/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2323 - accuracy: 0.9136 - val_loss: 0.3869 - val_accuracy: 0.8300\n",
      "Epoch 85/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2189 - accuracy: 0.9263 - val_loss: 0.3860 - val_accuracy: 0.8267\n",
      "Epoch 86/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.1939 - accuracy: 0.9317 - val_loss: 0.3498 - val_accuracy: 0.8400\n",
      "Epoch 87/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2141 - accuracy: 0.9191 - val_loss: 0.3675 - val_accuracy: 0.8433\n",
      "Epoch 88/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2023 - accuracy: 0.9297 - val_loss: 0.3521 - val_accuracy: 0.8467\n",
      "Epoch 89/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2047 - accuracy: 0.9171 - val_loss: 0.3808 - val_accuracy: 0.8300\n",
      "Epoch 90/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.1886 - accuracy: 0.9354 - val_loss: 0.3709 - val_accuracy: 0.8300\n",
      "Epoch 91/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.1886 - accuracy: 0.9289 - val_loss: 0.3826 - val_accuracy: 0.8400\n",
      "Epoch 92/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2102 - accuracy: 0.9196 - val_loss: 0.3761 - val_accuracy: 0.8400\n",
      "Epoch 93/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.1499 - accuracy: 0.9515 - val_loss: 0.3841 - val_accuracy: 0.8267\n",
      "Epoch 94/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.2038 - accuracy: 0.9243 - val_loss: 0.3807 - val_accuracy: 0.8300\n",
      "Epoch 95/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.1898 - accuracy: 0.9336 - val_loss: 0.3812 - val_accuracy: 0.8400\n",
      "Epoch 96/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.1745 - accuracy: 0.9321 - val_loss: 0.3734 - val_accuracy: 0.8367\n",
      "Epoch 97/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.1852 - accuracy: 0.9325 - val_loss: 0.3690 - val_accuracy: 0.8467\n",
      "Epoch 98/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.1914 - accuracy: 0.9233 - val_loss: 0.3624 - val_accuracy: 0.8400\n",
      "Epoch 99/100\n",
      "30/30 [==============================] - 47s 2s/step - loss: 0.1700 - accuracy: 0.9464 - val_loss: 0.3736 - val_accuracy: 0.8367\n",
      "Epoch 100/100\n",
      "30/30 [==============================] - 46s 2s/step - loss: 0.2076 - accuracy: 0.9121 - val_loss: 0.3867 - val_accuracy: 0.8300\n"
     ]
    }
   ],
   "source": [
    "# define model\n",
    "history = model.fit_generator(\n",
    "      train_generator,\n",
    "      steps_per_epoch=30,\n",
    "      epochs=100,\n",
    "      validation_data=validation_generator,\n",
    "      validation_steps=15)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "51a9aeb7",
   "metadata": {},
   "outputs": [],
   "source": [
    "#TO USE WITH EARLY STOPPING\n",
    "\n",
    "history = model.fit_generator(\n",
    "      train_generator,\n",
    "      steps_per_epoch=63,\n",
    "      epochs=100,\n",
    "      validation_data=validation_generator,\n",
    "      validation_steps=44,\n",
    "      callbacks=[es,mc])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d9dc8b61",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "cbdce7fb",
   "metadata": {},
   "outputs": [],
   "source": [
    "#save model\n",
    "model_json=model.to_json()\n",
    "with open(\"densenetAdagradswish.json\", \"w\") as json_file:\n",
    "    json_file.write(model_json)\n",
    "#serializar los pesos\n",
    "model.save_weights(\"densenetAdagradswish.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "b05790e8",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\IDEA\\Anaconda3\\envs\\gputest\\lib\\site-packages\\tensorflow\\python\\keras\\engine\\training.py:1905: UserWarning: `Model.predict_generator` is deprecated and will be removed in a future version. Please use `Model.predict`, which supports generators.\n",
      "  warnings.warn('`Model.predict_generator` is deprecated and '\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "16/16 [==============================] - 13s 605ms/step\n"
     ]
    }
   ],
   "source": [
    "predictions=model.predict_generator(validation_generator, steps=len(validation_generator), verbose=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "30f61bd8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "val_preds = np.round(predictions)# from probabilities to 0 or 1\n",
    "val_trues = validation_generator.classes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "815d8a65",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Confusion Matrix\n",
      "[[ 11   2   2   5]\n",
      " [  2  73   8   8]\n",
      " [  2  13 118   3]\n",
      " [  0   4   4  58]]\n"
     ]
    }
   ],
   "source": [
    "#modify:\n",
    "from sklearn.metrics import confusion_matrix\n",
    "from sklearn.metrics import classification_report\n",
    "import numpy as np\n",
    "num_of_test_samples = 313 #number of testing samples\n",
    "batch_size=20 #batch size for the validation set\n",
    "Y_pred = model.predict_generator(validation_generator, num_of_test_samples // batch_size+1)\n",
    "y_pred = np.argmax(Y_pred, axis=1)\n",
    "print('Confusion Matrix')\n",
    "print(confusion_matrix(validation_generator.classes, y_pred))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "fcd5652d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Classification Report\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "        croc       0.73      0.55      0.63        20\n",
      "       hyena       0.79      0.80      0.80        91\n",
      "     leopard       0.89      0.87      0.88       136\n",
      "        lion       0.78      0.88      0.83        66\n",
      "\n",
      "    accuracy                           0.83       313\n",
      "   macro avg       0.80      0.77      0.78       313\n",
      "weighted avg       0.83      0.83      0.83       313\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print('Classification Report')\n",
    "target_names = ['croc', 'hyena', 'leopard', 'lion']\n",
    "print(classification_report(validation_generator.classes, y_pred, target_names=target_names))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f8f01c0",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad6ed72d",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "34cbf1e7",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "7d2e2230",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[14  0]\n",
      " [ 1  8]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "val_preds = np.round(predictions) # from probabilities to 0 or 1\n",
    "val_trues = validation_generator.classes\n",
    "from sklearn.metrics import confusion_matrix\n",
    "mat= confusion_matrix (val_trues,val_preds)\n",
    "print(mat)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "c17b1c44",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.93      1.00      0.97        14\n",
      "           1       1.00      0.89      0.94         9\n",
      "\n",
      "    accuracy                           0.96        23\n",
      "   macro avg       0.97      0.94      0.95        23\n",
      "weighted avg       0.96      0.96      0.96        23\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import classification_report\n",
    "print(classification_report(val_trues,val_preds))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "9e82b384",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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iEjMKdCLiMScAr2ISMw1yjZ6EalfGzdupLy8nG+//Tb7ytKg2rRpQ1FRES1btsx5GwV6EaG8vJx27dpRUlJC+ufGSENzd1auXEl5eTndu3fPebvYNN1MmwYlJbDdduF9mh6VLJKzb7/9lo4dOyrIN3JmRseOHat95RWLGv20aTBuHKyPHluxbFmYBhg1quHSJdKUKMg3DTX5nmJRo584sSLIJ6xfH+aLiDR3sQj0H31Uvfki0risXLmS0tJSSktL2XXXXenatevW6e+//z7jtnPmzOGcc87JeoyBAwfmJa2zZs3i6KOPzsu+6kssAn23qg9iyzJfRGon331iHTt2ZP78+cyfP5/x48czYcKErdOtWrVi06ZNabctKyvjuuuuy3qMl156qXaJbMJiEeivvBIKCyvPKywM80UkvxJ9YsuWgXtFn1i+b4AYO3Ys5513HocccggXXnghr732GgMHDqRv374MHDiQxYsXA5Vr2JMnT+a0005j6NCh9OjRo1IB0LZt263rDx06lBNOOIGePXsyatQoEqP4zpgxg549ezJ48GDOOeecrDX3VatWcdxxx7HffvsxYMAA3nzzTQCee+65rVckffv2Ze3atXz66acMGTKE0tJS9tlnH55//vn8nrAMYtEZm+hwnTgxNNd06xaCvDpiRfIvU59Yvv/n3n33XWbOnElBQQFr1qxh9uzZtGjRgpkzZ/L73/+e+++/f5ttFi1axLPPPsvatWvZa6+9OOOMM7a55/yNN95g4cKF/OAHP2DQoEG8+OKLlJWV8atf/YrZs2fTvXt3Ro4cmTV9kyZNom/fvjz00EM888wznHLKKcyfP58pU6Zw/fXXM2jQINatW0ebNm2YOnUqRxxxBBMnTmTz5s2sr3oS61AsAj2EPzAFdpG6V599Yj/72c8oKCgAYPXq1YwZM4b33nsPM2Pjxo0ptznqqKNo3bo1rVu3pkuXLnz++ecUFRVVWqd///5b55WWlrJ06VLatm1Ljx49tt6fPnLkSKZOnZoxfS+88MLWwubHP/4xK1euZPXq1QwaNIjzzjuPUaNGMWLECIqKijjggAM47bTT2LhxI8cddxylpaW1OTXVEoumGxGpP/XZJ7bDDjts/XzppZdyyCGHsGDBAh555JG095K3bt166+eCgoKU7fup1qnJQ5hSbWNmXHTRRdx8881s2LCBAQMGsGjRIoYMGcLs2bPp2rUro0eP5m9/+1u1j1dTWQO9md1iZl+Y2YI0y883s/nRa4GZbTaznaNlS83srWiZxh0WiYGG6hNbvXo1Xbt2BeC2227L+/579uzJBx98wNKlSwG45557sm4zZMgQpkWdE7NmzaJTp07suOOOvP/+++y7775ceOGFlJWVsWjRIpYtW0aXLl04/fTT+cUvfsG8efPynod0cqnR3wYMS7fQ3a9291J3LwUuBp5z91VJqxwSLS+rVUpFpFEYNQqmToXiYjAL71On1n3T6QUXXMDFF1/MoEGD2Lx5c973v/3223PDDTcwbNgwBg8ezC677MJOO+2UcZvJkyczZ84c9ttvPy666CJuv/12AK655hr22Wcf+vTpw/bbb8/w4cOZNWvW1s7Z+++/n9/85jd5z0M6OT0z1sxKgEfdfZ8s690FPOvuN0XTS4Eyd/+yOokqKytzPXhEpP6888477L333g2djAa3bt062rZti7tz1llnscceezBhwoSGTtY2Un1fZjY3XYU6b230ZlZIqPknd4M78JSZzTWzcfk6lohIXbjpppsoLS2ld+/erF69ml/96lcNnaS8yOddNz8BXqzSbDPI3ZebWRfgH2a2yN1np9o4KgjGAXTTL51EpAFMmDChUdbgayufd92cBNydPMPdl0fvXwAPAv3TbezuU929zN3LOndO+XxbERGpgbwEejPbCTgY+HvSvB3MrF3iM/CvQMo7d0REpO5kbboxs7uBoUAnMysHJgEtAdz9z9FqxwNPufs3SZvuAjwYDanZArjL3Z/IX9JFRCQXWQO9u2f9HbC730a4DTN53gdAn5omTERE8kO/jBWRBjd06FCefPLJSvOuueYazjzzzIzbJG7DPvLII/n666+3WWfy5MlMmTIl47Efeugh3n777a3Tl112GTNnzqxG6lNrTMMZK9CLSIMbOXIk06dPrzRv+vTpOQ0sBmHUyfbt29fo2FUD/RVXXMFhhx1Wo301Vgr0ItLgTjjhBB599FG+++47AJYuXcry5csZPHgwZ5xxBmVlZfTu3ZtJkyal3L6kpIQvvwy/y7zyyivZa6+9OOyww7YOZQzhHvkDDjiAPn368NOf/pT169fz0ksv8fDDD3P++edTWlrK+++/z9ixY7nvvvsAePrpp+nbty/77rsvp5122tb0lZSUMGnSJPr168e+++7LokWLMuavoYczjs3olSKSH+eeC/Pn53efpaVwzTXpl3fs2JH+/fvzxBNPcOyxxzJ9+nROPPFEzIwrr7ySnXfemc2bN3PooYfy5ptvst9++6Xcz9y5c5k+fTpvvPEGmzZtol+/fuy///4AjBgxgtNPPx2ASy65hL/+9a+cffbZHHPMMRx99NGccMIJlfb17bffMnbsWJ5++mn23HNPTjnlFG688UbOPfdcADp16sS8efO44YYbmDJlCjfffHPa/DX0cMaq0YtIo5DcfJPcbHPvvffSr18/+vbty8KFCys1s1T1/PPPc/zxx1NYWMiOO+7IMcccs3XZggUL+NGPfsS+++7LtGnTWLhwYcb0LF68mO7du7PnnnsCMGbMGGbPrvi954gRIwDYf//9tw6Els4LL7zA6NGjgdTDGV933XV8/fXXtGjRggMOOIBbb72VyZMn89Zbb9GuXbuM+86FavQiUkmmmnddOu644zjvvPOYN28eGzZsoF+/fnz44YdMmTKF119/nQ4dOjB27Ni0wxMnRLd0b2Ps2LE89NBD9OnTh9tuu41Zs2Zl3E+2ccASQx2nGwo5274SwxkfddRRzJgxgwEDBjBz5sytwxk/9thjjB49mvPPP59TTjkl4/6zUY1eRBqFtm3bMnToUE477bSttfk1a9awww47sNNOO/H555/z+OOPZ9zHkCFDePDBB9mwYQNr167lkUce2bps7dq17LbbbmzcuHHr0MIA7dq1Y+3atdvsq2fPnixdupQlS5YAcMcdd3DwwQfXKG8NPZyxavQi0miMHDmSESNGbG3C6dOnD3379qV379706NGDQYMGZdy+X79+nHjiiZSWllJcXMyPfvSjrcv+8Ic/cOCBB1JcXMy+++67NbifdNJJnH766Vx33XVbO2EB2rRpw6233srPfvYzNm3axAEHHMD48eNrlK/Jkydz6qmnst9++1FYWFhpOONnn32WgoICevXqxfDhw5k+fTpXX301LVu2pG3btnl5QElOwxTXNw1TLFK/NExx09JgwxSLiEjjpEAvIhJzCvQiAmS/y0Qah5p8Twr0IkKbNm1YuXKlgn0j5+6sXLmSNm3aVGs73XUjIhQVFVFeXs6KFSsaOimSRZs2bSgqKqrWNgr0IkLLli3p3r17QydD6oiabkREYk6BXkQk5hToRURiToFeRCTmFOhFRGJOgV5EJOayBnozu8XMvjCzBWmWDzWz1WY2P3pdlrRsmJktNrMlZnZRPhMuIiK5yaVGfxswLMs6z7t7afS6AsDMCoDrgeFAL2CkmfWqTWJFRKT6sgZ6d58NrKrBvvsDS9z9A3f/HpgOHFuD/YiISC3kq43+IDP7p5k9bma9o3ldgY+T1imP5omISD3KxxAI84Bid19nZkcCDwF7AKke3Jh2xCQzGweMA+jWrVsekiUiIpCHGr27r3H3ddHnGUBLM+tEqMHvnrRqEbA8w36munuZu5d17ty5tskSEZFIrQO9me1q0WPXzax/tM+VwOvAHmbW3cxaAScBD9f2eCIiUj1Zm27M7G5gKNDJzMqBSUBLAHf/M3ACcIaZbQI2ACd5GNR6k5n9GngSKABucfeFdZILERFJSw8HFxGJAT0cXESkGVOgFxGJOQV6EZGYU6AXEYk5BXoRkZhToBcRiTkFehGRmFOgFxGJOQV6EZGYU6AXEYk5BXoRkZhToBcRiTkFehGRmFOgFxGJOQV6EZGYU6AXEYk5BXoRkZhToBcRiTkFehGRmFOgFxGJOQV6EZGYyxrozewWM/vCzBakWT7KzN6MXi+ZWZ+kZUvN7C0zm29mc/KZcBERyU0uNfrbgGEZln8IHOzu+wF/AKZWWX6Iu5e6e1nNkigiIrXRItsK7j7bzEoyLH8pafIVoCgP6RIRkTzJdxv9L4DHk6YdeMrM5prZuEwbmtk4M5tjZnNWrFiR52SJiDRfWWv0uTKzQwiBfnDS7EHuvtzMugD/MLNF7j471fbuPpWo2aesrMzzlS4RkeYuLzV6M9sPuBk41t1XJua7+/Lo/QvgQaB/Po4nIiK5q3WgN7NuwAPAaHd/N2n+DmbWLvEZ+Fcg5Z07IiJSd7I23ZjZ3cBQoJOZlQOTgJYA7v5n4DKgI3CDmQFsiu6w2QV4MJrXArjL3Z+ogzyIiEgGudx1MzLL8l8Cv0wx/wOgz7ZbiIhIfdIvY0VEYk6BXkQk5hToRURiToFeRCTmFOhFRGJOgV5EJOYU6EVEYk6BXkQk5hToRURiToFeRCTmFOhFRGJOgV5EJOYU6EVEYk6BXkQk5hToRURiToFeRCTmFOhFRGJOgV5EJOYU6EVEYk6BXkQk5hToRURiLmugN7NbzOwLM1uQZrmZ2XVmtsTM3jSzfknLhpnZ4mjZRflMuIiI5CaXGv1twLAMy4cDe0SvccCNAGZWAFwfLe8FjDSzXrVJrIiIVF/WQO/us4FVGVY5FvibB68A7c1sN6A/sMTdP3D374Hp0boiIlKP8tFG3xX4OGm6PJqXbn5KZjbOzOaY2ZwVK1bkIVkiIgL5CfSWYp5nmJ+Su0919zJ3L+vcuXMekiUiIgAt8rCPcmD3pOkiYDnQKs18ERGpR/mo0T8MnBLdfTMAWO3unwKvA3uYWXczawWcFK0rIiL1KGuN3szuBoYCncysHJgEtARw9z8DM4AjgSXAeuDUaNkmM/s18CRQANzi7gvrIA8iIpJB1kDv7iOzLHfgrDTLZhAKAhERaSD6ZayISMwp0IuIxJwCvYhIzCnQi4jEnAK9iEjMKdCLiMScAr2ISMwp0IuIxJwCvYhIzCnQi4jEnAK9iEjMKdCLiMScAr2ISMzFJtBv2QJlZTBlSkOnRESkcYlNoN9uO/jsM1i4EKZNg5KSMK+kJEyLiDRX+XiUYKNRUgKvvgr33gvr14d5y5bBuHHh86hRDZY0EZEGE5saPYRA/+67FUE+Yf16mDixQZIkItLgYhXou3eHzZtTL/voo/pNi4hIYxGrQF9Skn5Zt271lgwRkUYlloG+devK8wsL4cor6z05IiKNQiwD/ZgxUFwMZuF96lR1xIpI85XTXTdmNgy4FigAbnb3/6qy/HwgEUpbAHsDnd19lZktBdYCm4FN7l6Wp7RvY/fdQ3DfdVdYurSujiIi0rRkDfRmVgBcDxwOlAOvm9nD7v52Yh13vxq4Olr/J8AEd1+VtJtD3P3LvKY8hVatoGtXBXkRkWS5NN30B5a4+wfu/j0wHTg2w/ojgbvzkbia6N5dgV5EJFkugb4r8HHSdHk0bxtmVggMA+5Pmu3AU2Y218zGpTuImY0zszlmNmfFihU5JCu1khIFehGRZLkEeksxz9Os+xPgxSrNNoPcvR8wHDjLzIak2tDdp7p7mbuXde7cOYdkpVZSAuXlsHFjjXchIhIruQT6cmD3pOkiYHmadU+iSrONuy+P3r8AHiQ0BdWZkpIwwFl5eV0eRUSk6cgl0L8O7GFm3c2sFSGYP1x1JTPbCTgY+HvSvB3MrF3iM/CvwIJ8JDydxC2WH35Yl0cREWk6sgZ6d98E/Bp4EngHuNfdF5rZeDMbn7Tq8cBT7v5N0rxdgBfM7J/Aa8Bj7v5E/pK/rUSgT7TTayRLEWnuzD1dc3vDKSsr8zlz5tRo240boU2bMIjZXnuFkSuTBzkrLNQPqEQkfsxsbrrfKcXql7EALVtCUVGo0U+cqJEsRURiF+ih4hbLdCNWaiRLEWlOYh3o041YqZEsRaQ5iW2gLy+Hyy8PbfLJNJKliDQ3sQ307jB4cOh41UiWItKcxeqZsQndu4f3pUtDUFdgF5HmLLY1etCYNyIiENNAX1QEBQUK9CIiENNA36JF+LHUffdtex+9iEhzE8tAD3DNNbBoEZx/fsU8DYcgIs1RLDtjAQ4/HH77W/if/4Fhw2DNmsrDISxbFqZBnbUiEm+xG+sm2XffwYEHwiefhPFvUg1dXFystnwRafqa1Vg3yVq3hrvugnXr0o9Pr+EQRCTuYh3oAXr1gjPPTL/cXe31IhJvsQ/0AKefHt5btky9PNFer2AvInHULAJ9z54wZAh06JB+QDMNXywicdUsAj2EGvsXX8Att4Rxb1JRe72IxFGzCfQ//Wmo0d90k4YvFpHmpdkE+jZt4JRT4IEH4MILNXyxiDQfzSbQQ+iU3bgRHnssjIeT0LWrhi8WkfhqVoG+d28YOjQE+rZtw/AI7duHWywvukhDI4hIPOUU6M1smJktNrMlZnZRiuVDzWy1mc2PXpflum19e+SR0Ck7dy5cdRWcdRYsXx5+UOUebrUcPTp02Croi0gcZA30ZlYAXA8MB3oBI82sV4pVn3f30uh1RTW3rTdt20LnzhXTd9657TqJUSEU9EUkDnKp0fcHlrj7B+7+PTAdODbH/ddm23qR7ZbK5KCvH1WJSFOUS6DvCnycNF0ezavqIDP7p5k9bma9q7ktZjbOzOaY2ZwVK1bkkKz8qM4tlevXw8knq3YvIk1LLoE+1c+Lqg55OQ8odvc+wB+Bh6qxbZjpPtXdy9y9rHNy20odu/LKbW+1zEa1exFpSnIJ9OXA7knTRcDy5BXcfY27r4s+zwBamlmnXLZtaKNGhVsri4vDdLpfzVbVlGv3mzY1dApEpD7lEuhfB/Yws+5m1go4CXg4eQUz29UshEgz6x/td2Uu2zYGo0aFMend4Y47qhf0ly2DU0+FTp3C7ZmdOlV8boyFwFtvhV8IT55c0f8gIvGWNdC7+ybg18CTwDvAve6+0MzGm9n4aLUTgAVm9k/gOuAkD1JuWxcZyZd0QT+TjRth5cqwzcqVFZ8b4107V10Vxue//PLwOwIFe5H4i/UTpvJl2rTKjyGsqcLChv0F7scfQ48e4bcDmzfDn/4E48fD9deHKxARaboyPWEqts+MzadEYJ44MdTSa2r9ejj3XNhjj3Cl0KVL7n0C+XDNNaEGP2FCuNtohx3gv/8bVqyAv/2t+p3SItI0qB6Xo0STzp131i4gfvlleI7trrvCMcfA6tV5S2JGX38driZOPDEUMmbwn/8ZHp7+wANw8MHw6af1kxYRqV8K9NWUfJeOGXTsCK1a1Wxfjz4afqX7v/+77TL3cAXw/fe1S2/CX/4S2uZ/97uKeWZw3nnw0EPwzjvQv3/I2+LF4fgrVsCtt8IJJ4TtRaRpUht9HkybFpp1PvoIdt45zFu5MgTSXE/voYeGRx1+8EEYi2ft2tCObhZG1+zeHQYODIOvtW9feVt3ePVVuP12eOGFUPjsuivssku4w6Z9+9AJ26sXzJyZ+vjz54eA/v77YXrnncNVwJYtYdiIdetCPn/+84ptPvssvHr3Tv+Yxm++CX0De+1Vv81Ujcnq1eEcFhQ0dEokzjK10SvQ16FEAZBru36rVlBaGmrWO+4YXhs2wIcfhgLgpZfCrZv//d/hyuK112DGDLj//lAL33770ATzzTchAH/+OaxZU7H/mTNDgZKOO7z3HsyeHY7VrRsceyzsvTcMGxbmPf54OMa118Jll4WrjtatQ7oPOggOOyws37AB/vjH0OH71VfhrqMTTgjLPvss5GnDBjj77FCINQaffBLyN3p0yFNNbdkC8+aF72bGjPA9HXVUaCJLVyBm4w4vvxwK4pNPrp9C073mx1m1ChYuDH8fGzaEv9vBg/ObPqksU6DH3Rvda//99/c4KS52D/822V9m4b242P3OOyvvZ+5c9wEDwvLWrcN7QYH7wQe733yz++rV2x570yb3lSvdP/usdnn46iv3ffd1b9fOvbQ0HPvoo0Maf/e7kIY2bcL8li0rPh97rPuf/uR+5JFhfiKfBQXurVqFfFx6qfs337h/+qn79Olhfxde6P6HP7j/8Y/uX35ZOS1r1rifc477Y49tm87Nm923bKl+/r7/3v2AA0La9t7b/eWXq7f9d9+533ef+5gx7l26VHyXBx7ofuqpYXrUqJC+6li92v2229z79as4dyNHum/YkHr9xYvD+fz668rz1693v+QS94ULczvu99+7Dx7sfvjh7itWpF9v3Tr35593v+ce92uucR8/3r1379R/27femtuxc/XWW+5LluR3n00ZMMfTxNQGD+qpXnEL9Hfe6V5YmHuwrxr0O3YMLzP3bt3cx41zP+MM93vvDQE4cYzi4rBOqkIiH8rLw/F33dX9//5v24C6YYP7zJnuF1zgfvbZ7m+/XXn5V1+5v/CC+9Kl7hs3hv2NHBny2LZtRb5bt64oyCAc85VXwj4+/ti9T5+KwmLatIr9v/KKe48e7oMGuS9fnj4fW7Zsm/ZLLw37vOgi9913D+fxzDPdZ81KH1Q3bQp5mDQpnBNw79Ah5Olvf3P/4ouKda+8Miw/++zsBdGMGe4nn+zes2fF30CvXu433lixn0GDKu9/40b3//qvivP2859X3ue554b5nTq5z5+f+fju7pdfXlFo9+ixbQHx3XehAN9ll8p/s23buh9xhPu//7v7E0+4v/ii+7x57occ4r799iE4J3zwQSiwX389fTo+/zwUIIsWVZ4/b17Y33bbhXNVdXlTVZNKSoICfSOQCMTJAbymr6q1/lQFSWFh3QT7NWtC7TCfnnvOfexY96uucn/ttRC03EOt8uWX3UtKQsC55BL33XYLVxX33+8+dGg4F3/5i/vVV7u3aBGCdGGhe9euYV8JX34ZCqexY0Nw2m0397vvDv9YL74YAsaYMWHd1atDQbrdduFctmrlvv/+7vvsE/a7ww6hkEk+38OHhwCdSHtVW7a4//a3Yd1+/cIVzqhR7v/5n6EW7h4KjZ/+NKzTpYv7Mce4X3FFOD/JAeDee8MVU+fO7j/6kfvxx1cUfscf7z5hQvh8991h/Zkzw/S//Zt7UZH7zjuHq8N05s8P5/LnPw/nf5dd3Hfc0f2yy8Lrggvc/+Vfwj6HDHH/+9/d33wz1PzTXbF8+mnYT8+e7mvXhnPVoUPF+Rs7NhTOmzeHdWfNCgG8VattC6jPPw+Ff1GR+3nnhe97u+3ClebAge4//nEoHKrj229Tz3vuucpXNFu2uC9YEPZ/yy3uzz4bKi6ffBLelywJhWB1ffZZKIwPO6zmwV6BvpFJDvq1fRUWhtp+qmXFxQ2d0/xYtSo0EyVq94la4fr1IcAm8jtiRFh3/vxQOLRuHYJl8rlu3979xBPdy8rC9LBhocbavfu2TV+rVrk//HBoSjr8cPfjjgvNMBMmuP/+9yEI/8//uL/3Xm752LIlbHP44aHgSE5Xr16hAGvTxv0//iN7sHj11ZCPoUNDAdS7d8VV1saNoYmvfftwroqK3PfcMzSPvf9+OIft24ermOnTQ5BOLlz79g0FTaLJbNmyivOVKPj69g1NZ9UJSk8/HQLyfvuFArpPn1Azv+CCsM9WrSo377VrF66AnnwyFOAdOri/9FIoXNq0cZ8zJ+z388/D93H00e6HHhrOJbg/+mhu6brkklBw/+Qn7g89FPZ35ZUVV2kQmi3HjHH/4Q+z/0/uuGMoVO+80/2jjzKfo88/dz///HB1UlAQ/r5qWpFSoG+katqkU52af+I4dd2sU9c2b3Z/8MHwj5Hsu+9Cre4vf6n8D7ViRfjH/eEPwz/dVVeFtuREQNu0yf3aa0NTw3bbhSalhvDRR+7XXRdqoSNG5K/N+b33wpVHmzYhgCRf3Xz4YeiPSFyxQFj30ENDwQjuDzxQeX9btoQabm2aFtwrmoTGjAkFT8KSJaEAvfhi9+uvDwXsmjWV09y9e8XVbKa/4W+/DYVJly6V/17eeMP99tsrX3X98Y9hfwcfXDmwQ2iCuueeEPQPPTQUNEccEZrQli0LheY//uF+003uf/6z+1//Gmr5v/xl5Sat9u1Df8eECe6PPBL6T9580/0XvwiVkUTz07vv1u7cKtA3Yvls0kn16tix4vK3arNOHAqA2iovr37Ha1MxdWr4vidPTr18w4Zw9XPnne6//nWopW+3XWhSqitbtoSmqpoUGB9/7N6/f+gTyWbBghBEjzoqXKVcfnlojoJQCDz/fOg8NwuF28aN4fXww+Hq4J//rH76km3eHK66rr8+NAMOHlxxg0KigN1++9B5na/+BQX6JqKug36qGn+qAiBVmppzYdCUvf129YLqN9+Eq504uPZa39rcB6HPYdq0iukWLdwPOqjylUVd2rAhtOlfdpn7lCnhbrh8UqBvgpIDbOKum/ooABLBPF2BU1edvCL5tmVLaLfv0CE0wSSsWxdq7Uccse2tu01ZpkCvH0w1MdX9EVZN5PKL3uLi8HSuUaNS/zJ41arwg6vEOiINYdOm8GrTpqFTUvcy/WBKY900MZkGVyssDMMf1FYuZX/yWPujR4dp923H48/2yMVp08KvZhMPajnzzMrTjWEMf2m6WrRoHkE+GwX6Jqrq4GrFxWH62mu3LQBatsxPAVBVokDIVDCkeuRiIrhXLSSWLYMbb6w8rWfzitSeAn0Tlqjdb9kS3keNSl0A3HprGB451VVAfQ00luoKALJfPdT02bxVrxRSbZvLOiKxkK7xviFf6oytO6nuosn24636uAOoOncJJd/9kyo/ufxSuD5/TSxSH1BnrGSS6lGJiQ7ZRKcr5OdxivmSSF/VjuNMHcnFxeHKB0INPlWHdvI6qSR3PKuzWRoTdcZKRqmae+64IwTMVE1CsG2TT2K6Y8e66Q+oKl3/QKZ6y0cfVTTXpLtr6aOP0m+fKBCT+xAa28PfRVJKV9VvyJeabhq/bD+kqs7wDslNMmeckb9xgGrSDJXcnJX8GwazbQcyq2nTkkhdoLY/mAKGAYuBJcBFKZaPAt6MXi8BfZKWLQXeAuZnSkjyS4E+HjL98CrTuPuJbetyHKBMgToffRKFhaHQqpqHVENPpysYcllHhYck1CrQAwXA+0APoBXwT6BXlXUGAh2iz8OBV5OWLQU6ZTtO8kuBPn5qEpzqc0iIhu5wzqWQyVZ4ZDqvKhzir7aB/iDgyaTpi4GLM6zfAfgkaVqBXmotl6uDVMM15BJkszXJNKZXtrSmG68oX3cY1abAUGFTt2ob6E8Abk6aHg38KcP6v6uy/ofAPGAuMC7DduOAOcCcbt261cd5kSYqXcCoya2jNWkeSgTbhr4KyPTKpb8jU39Erv0u2QoMjZtUf2ob6H+WItD/Mc26hwDvAB2T5v0geu8SNfsMyXZM1eglX1IFp6pNHdXp/E0OTvU92mhdvLI1FSUH4lwKjeqel4KCzDX86hREzV29NN0A+0Vt+Xtm2Ndk4HfZjqlAL/lUkzuEsnWapjtGTYNqY31VpzCsbWd21XOebV+pvqPqFgaNpTkpH+mobaBvAXwAdE/qjO1dZZ1u0R05A6vM3wFol/T5JWBYtmMq0Et9y9c/fKbmjVyHnk4V8Bqy8GiKBVSmc5/LL6irrp9oBsv16qM6f0P56kPJx+2VRwLvRjX2idG88cD46PPNwFfRLZRbb6OM7tT5Z/RamNg220uBXpqy6v7DZ1s/XW26Jk1PzfWVrjBN9erYMXvfTS5DauR6xZHp+62OTIFeQyCINHKphqgoLAy/VE4Mv5BqnaoKC2H77cMw0g0lMURFQQFs3txw6ciHxPAgtXk+RGFh+u/MLAxYmCsNgSDShKUbkjp5jJ1U65xxRm7DWNdk+IqOHbfdTzqJ/ScPrXH77blv31glhsCozUOAMhXM3brVfL/bSFfVb8iXmm5E6k5Nm4rStWNnahrJtQO7Op2u2daPw6tB2ujr+6VAL9JwcrklNdU2tenMru5tlOnWz6UDu7G/6uKuG7XRi8g2mvpwzJmG3q46lHW2voviYjjySJgxI/dmmlyeu5xuu+q0y1feVm30IlINqZ5e1pRkGnr7jjty67soLAxPZVu6FG64IbwnhulOJ7FN8jESfR/Jn9PJa7t8snRV/YZ8qelGROpbLs1PNWnWSnesfD/hjAxNNy3qqPwQEWlSEg/YybYO1L5ZK1/7yZXa6EVEYkBt9CIizZgCvYhIzCnQi4jEnAK9iEjMKdCLiMRco7zrxsxWADUdKqgT8GUek9MUNMc8Q/PMd3PMMzTPfFc3z8Xu3jnVgkYZ6GvDzOaku8UorppjnqF55rs55hmaZ77zmWc13YiIxJwCvYhIzMUx0E9t6AQ0gOaYZ2ie+W6OeYbmme+85Tl2bfQiIlJZHGv0IiKSRIFeRCTmYhPozWyYmS02syVmdlFDp6eumNnuZvasmb1jZgvN7DfR/J3N7B9m9l703qGh05pvZlZgZm+Y2aPRdHPIc3szu8/MFkXf+UFxz7eZTYj+theY2d1m1iaOeTazW8zsCzNbkDQvbT7N7OIovi02syOqc6xYBHozKwCuB4YDvYCRZtarYVNVZzYBv3X3vYEBwFlRXi8Cnnb3PYCno+m4+Q3wTtJ0c8jztcAT7t4T6EPIf2zzbWZdgXOAMnffBygATiKeeb4NGFZlXsp8Rv/jJwG9o21uiOJeTmIR6IH+wBJ3/8DdvwemA8c2cJrqhLt/6u7zos9rCf/4XQn5vT1a7XbguAZJYB0xsyLgKODmpNlxz/OOwBDgrwDu/r27f03M8w20ALY3sxZAIbCcGObZ3WcDq6rMTpfPY4Hp7v6du38ILCHEvZzEJdB3BT5Omi6P5sWamZUAfYFXgV3c/VMIhQHQpQGTVheuAS4Akh+dHPc89wBWALdGTVY3m9kOxDjf7v4JMAX4CPgUWO3uTxHjPFeRLp+1inFxCfSWYl6s7xs1s7bA/cC57r6modNTl8zsaOALd5/b0GmpZy2AfsCN7t4X+IZ4NFmkFbVJHwt0B34A7GBmJzdsqhqFWsW4uAT6cmD3pOkiwuVeLJlZS0KQn+buD0SzPzez3aLluwFfNFT66sAg4BgzW0polvuxmd1JvPMM4e+63N1fjabvIwT+OOf7MOBDd1/h7huBB4CBxDvPydLls1YxLi6B/nVgDzPrbmatCJ0WDzdwmuqEmRmhzfYdd//fpEUPA2Oiz2OAv9d32uqKu1/s7kXuXkL4bp9x95OJcZ4B3P0z4GMz2yuadSjwNvHO90fAADMrjP7WDyX0Q8U5z8nS5fNh4CQza21m3YE9gNdy3qu7x+IFHAm8C7wPTGzo9NRhPgcTLtneBOZHryOBjoRe+vei950bOq11lP+hwKPR59jnGSgF5kTf90NAh7jnG7gcWAQsAO4AWscxz8DdhH6IjYQa+y8y5ROYGMW3xcDw6hxLQyCIiMRcXJpuREQkDQV6EZGYU6AXEYk5BXoRkZhToBcRiTkFehGRmFOgFxGJuf8HKAJFE493Wv4AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "#PLOT\n",
    "acc = history.history['accuracy']\n",
    "val_acc = history.history['val_accuracy']\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "epochs = range(len(acc))\n",
    "\n",
    "plt.plot(epochs, acc, 'bo', label='Training acc')\n",
    "plt.plot(epochs, val_acc, 'b', label='Validation acc')\n",
    "plt.title('Training and validation accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "plt.plot(epochs, loss, 'bo', label='Training loss')\n",
    "plt.plot(epochs, val_loss, 'b', label='Validation loss')\n",
    "plt.title('Training and validation loss')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "77f7809c",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40b275f2",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a93132bb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1536eb31",
   "metadata": {},
   "outputs": [],
   "source": [
    "#ENSEMBLE LEARNING"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "1a266eb4",
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.preprocessing import image\n",
    "import keras.backend as K\n",
    "import numpy as np\n",
    "import cv2\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "b399def3",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('densenetSGDrelu.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model1 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model1.load_weights(\"densenetSGDrelu.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "f336fd20",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('efficientSGD.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model2 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model2.load_weights(\"efficientSGD.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "b10d0f88",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('resnet.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model3 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model3.load_weights(\"resnet.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "963f6390",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('vgg19Adagrad.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model4 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model4.load_weights(\"vgg19Adagrad.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "9d613c1f",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar modelo:\n",
    "from keras.models import model_from_json\n",
    "# cargar json y crear el modelo\n",
    "json_file = open('resnetAdagrad.json', 'r')\n",
    "loaded_model_json = json_file.read()\n",
    "json_file.close()\n",
    "model5 = model_from_json(loaded_model_json)#change sequentially\n",
    "# cargar pesos al nuevo modelo\n",
    "model5.load_weights(\"resnetAdagrad.h5\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "86b12a64",
   "metadata": {},
   "outputs": [],
   "source": [
    "members=[model1,model2,model3,model4]#actualizar!!!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "46a17b78",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Stacked Test Accuracy: 0.821\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import cross_val_score\n",
    "from sklearn.metrics import accuracy_score\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.ensemble import ExtraTreesClassifier\n",
    "from sklearn.ensemble import GradientBoostingClassifier\n",
    "from sklearn.ensemble import AdaBoostClassifier\n",
    "from sklearn.ensemble import BaggingClassifier\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from keras.models import load_model\n",
    "from keras.utils import to_categorical\n",
    "from numpy import dstack\n",
    "\n",
    " \n",
    "# create stacked model input dataset as outputs from the ensemble\n",
    "def stacked_dataset(members, inputX):\n",
    "\tstackX = None\n",
    "\tfor model in members:\n",
    "\t\t# make prediction\n",
    "\t\tyhat = model.predict(inputX, verbose=0)\n",
    "\t\t# stack predictions into [rows, members, probabilities]\n",
    "\t\tif stackX is None:\n",
    "\t\t\tstackX = yhat\n",
    "\t\telse:\n",
    "\t\t\tstackX = dstack((stackX, yhat))\n",
    "\t# flatten predictions to [rows, members x probabilities]\n",
    "\tstackX = stackX.reshape((stackX.shape[0], stackX.shape[1]*stackX.shape[2]))\n",
    "\treturn stackX\n",
    " \n",
    "# fit a model based on the outputs from the ensemble members\n",
    "def fit_stacked_model(members, inputX, inputy):\n",
    "\t# create dataset using ensemble\n",
    "\tstackedX = stacked_dataset(members, inputX)\n",
    "\t# fit standalone model\n",
    "\t#model = LogisticRegression()#\n",
    "\tmodel = RandomForestClassifier(n_estimators=100, max_depth=None,max_features='auto',min_samples_split=2, random_state=0)# n_estimators=n of trees\n",
    "\t#model = ExtraTreesClassifier()\n",
    "\t#model = GradientBoostingClassifier()\n",
    "\t#model = AdaBoostClassifier(n_estimators=100)\n",
    "\t#model = BaggingClassifier(KNeighborsClassifier(),max_samples=0.5, max_features=0.5)\n",
    "\tmodel.fit(stackedX, inputy)\n",
    "\treturn model\n",
    " \n",
    "# make a prediction with the stacked model\n",
    "def stacked_prediction(members, model, inputX):\n",
    "\t# create dataset using ensemble\n",
    "\tstackedX = stacked_dataset(members, inputX)\n",
    "\t# make a prediction\n",
    "\tyhat = model.predict(stackedX)\n",
    "\treturn yhat\n",
    " \n",
    "\n",
    "# fit stacked model using the ensemble\n",
    "model = fit_stacked_model(members, x_train, y_train)\n",
    "# evaluate model on test set\n",
    "yhat = stacked_prediction(members, model, x_test)\n",
    "acc = accuracy_score(y_test, yhat)\n",
    "print('Stacked Test Accuracy: %.3f' % acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "historical-forth",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "\n",
    "filename = \"stacked_model.pickle\"\n",
    "\n",
    "# save model\n",
    "pickle.dump(model, open(filename, \"wb\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "soviet-breed",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.92      0.98      0.95       289\n",
      "           1       0.97      1.00      0.98        62\n",
      "           2       0.93      0.86      0.89       157\n",
      "           3       0.96      0.77      0.85       202\n",
      "           4       0.99      0.97      0.98       160\n",
      "\n",
      "   micro avg       0.95      0.91      0.93       870\n",
      "   macro avg       0.95      0.91      0.93       870\n",
      "weighted avg       0.95      0.91      0.92       870\n",
      " samples avg       0.91      0.91      0.91       870\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\IDEA\\Anaconda3\\envs\\gputest\\lib\\site-packages\\sklearn\\metrics\\_classification.py:1245: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in samples with no predicted labels. Use `zero_division` parameter to control this behavior.\n",
      "  _warn_prf(average, modifier, msg_start, len(result))\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import classification_report\n",
    "vp=np.round(yhat)\n",
    "vt=y_test\n",
    "target_names = ['alc', 'ant','hip', 'red', 'trag']\n",
    "print(classification_report(vt,vp,target_names=target_names))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "orange-surgery",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "9025e99b",
   "metadata": {},
   "outputs": [],
   "source": [
    "#cargar imagen para casificar\n",
    "\n",
    "from keras.preprocessing import image\n",
    "import keras.backend as K\n",
    "import numpy as np\n",
    "import cv2\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "877a33c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "#fosas de dientes de Marina (el modelo está en la carpeta \"pits\")\n",
    "from tensorflow.keras.applications.resnet50 import preprocess_input\n",
    "img_path = \"E:\\\\experimentos\\\\pits\\\\marina\\\\PIT\\\\FLKN+410+2.bmp\"\n",
    "#img_path = \"C:\\\\Users\\\\IDEA\\\\Documents\\\\experimentos\\\\pits\\\\HP1.37.bmp\"\n",
    "\n",
    "img = image.load_img(img_path, target_size=(250, 200))\n",
    "x = image.img_to_array(img)\n",
    "x = np.expand_dims(x, axis=0)\n",
    "x /= 255\n",
    "#x = preprocess_input(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "7c1f99f2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0. 0. 1. 0.]]\n"
     ]
    }
   ],
   "source": [
    "xxx = stacked_prediction(members, model, x)\n",
    "print(xxx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "detailed-measurement",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['my_random_forest.joblib']"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import joblib\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "# create RF\n",
    "rf = model\n",
    "\n",
    "# save\n",
    "joblib.dump(rf, \"my_random_forest.joblib\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "classical-potato",
   "metadata": {},
   "outputs": [],
   "source": [
    "# load\n",
    "loaded_rf = joblib.load(\"my_random_forest.joblib\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "scientific-newark",
   "metadata": {},
   "outputs": [],
   "source": [
    "# make a prediction with the stacked model\n",
    "def stacked_prediction2(members, model, inputX):\n",
    "\t# create dataset using ensemble\n",
    "\tstackedX = stacked_dataset(members, inputX)\n",
    "\t# make a prediction\n",
    "\tyhat = model.predict_proba(stackedX)\n",
    "\treturn yhat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "signal-baptist",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0. 0. 1. 0.]]\n"
     ]
    }
   ],
   "source": [
    "pred = stacked_prediction2(members, model, x)\n",
    "print(xxx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "convinced-infrastructure",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cathedral-maker",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
